From 622dfb2a4a66172514b447719851f6cee35865b8 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Thu, 19 Sep 2024 13:55:41 -0700 Subject: [PATCH 01/15] [lldb/Interpreter] Add requirements to Scripted Interface abstract methods (#109063) This patch adds new requirements to the Scripted Interface abstract method checker to check the minimum number of argument for abstract methods. This check is done when creating the interface object so the object is not created if the user implementation doesn't match the abstract method requirement. Signed-off-by: Med Ismail Bennani (cherry picked from commit 21026073e3b0583caf0c81564c4d7ebf002fe67b) --- .../Interfaces/ScriptedInterface.h | 17 +- .../OperatingSystemPythonInterface.h | 5 +- .../ScriptedPlatformPythonInterface.h | 11 +- .../ScriptedProcessPythonInterface.h | 9 +- .../Interfaces/ScriptedPythonInterface.h | 160 +++++++++++++----- .../ScriptedThreadPlanPythonInterface.h | 3 +- .../ScriptedThreadPythonInterface.h | 7 +- 7 files changed, 158 insertions(+), 54 deletions(-) diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h index c5fe672182b1d..f925fce04195d 100644 --- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h @@ -31,7 +31,22 @@ class ScriptedInterface { return m_object_instance_sp; } - virtual llvm::SmallVector GetAbstractMethods() const = 0; + struct AbstractMethodRequirement { + llvm::StringLiteral name; + size_t min_arg_count = 0; + }; + + virtual llvm::SmallVector + GetAbstractMethodRequirements() const = 0; + + llvm::SmallVector const GetAbstractMethods() const { + llvm::SmallVector abstract_methods; + llvm::transform(GetAbstractMethodRequirements(), abstract_methods.begin(), + [](const AbstractMethodRequirement &requirement) { + return requirement.name; + }); + return abstract_methods; + } template static Ret ErrorWithMessage(llvm::StringRef caller_name, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h index 321b6fa44daa7..8df48f1b64cc9 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h @@ -31,8 +31,9 @@ class OperatingSystemPythonInterface StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; - llvm::SmallVector GetAbstractMethods() const override { - return llvm::SmallVector({"get_thread_info"}); + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector({{"get_thread_info"}}); } StructuredData::DictionarySP CreateThread(lldb::tid_t tid, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h index 36a219a656993..a0da1bbc31c70 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h @@ -29,10 +29,13 @@ class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; - llvm::SmallVector GetAbstractMethods() const override { - return llvm::SmallVector( - {"list_processes", "attach_to_process", "launch_process", - "kill_process"}); + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector( + {{"list_processes"}, + {"attach_to_process", 2}, + {"launch_process", 2}, + {"kill_process", 2}}); } StructuredData::DictionarySP ListProcesses() override; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h index 1535d573e72f4..703b942fe5647 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h @@ -31,9 +31,12 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; - llvm::SmallVector GetAbstractMethods() const override { - return llvm::SmallVector( - {"read_memory_at_address", "is_alive", "get_scripted_thread_plugin"}); + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector( + {{"read_memory_at_address", 4}, + {"is_alive"}, + {"get_scripted_thread_plugin"}}); } StructuredData::DictionarySP GetCapabilities() override; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h index cb6f6ec398926..c715295eb9ff0 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -36,37 +36,78 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { eNotImplemented, eNotAllocated, eNotCallable, + eUnknownArgumentCount, + eInvalidArgumentCount, eValid }; - llvm::Expected> + struct AbstrackMethodCheckerPayload { + + struct InvalidArgumentCountPayload { + InvalidArgumentCountPayload(size_t required, size_t actual) + : required_argument_count(required), actual_argument_count(actual) {} + + size_t required_argument_count; + size_t actual_argument_count; + }; + + AbstractMethodCheckerCases checker_case; + std::variant payload; + }; + + llvm::Expected> CheckAbstractMethodImplementation( const python::PythonDictionary &class_dict) const { using namespace python; - std::map checker; -#define SET_ERROR_AND_CONTINUE(method_name, error) \ + std::map checker; +#define SET_CASE_AND_CONTINUE(method_name, case) \ { \ - checker[method_name] = error; \ + checker[method_name] = {case, {}}; \ continue; \ } - for (const llvm::StringLiteral &method_name : GetAbstractMethods()) { + for (const AbstractMethodRequirement &requirement : + GetAbstractMethodRequirements()) { + llvm::StringLiteral method_name = requirement.name; if (!class_dict.HasKey(method_name)) - SET_ERROR_AND_CONTINUE(method_name, - AbstractMethodCheckerCases::eNotImplemented) + SET_CASE_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotImplemented) auto callable_or_err = class_dict.GetItem(method_name); - if (!callable_or_err) - SET_ERROR_AND_CONTINUE(method_name, - AbstractMethodCheckerCases::eNotAllocated) - if (!PythonCallable::Check(callable_or_err.get().get())) - SET_ERROR_AND_CONTINUE(method_name, - AbstractMethodCheckerCases::eNotCallable) - checker[method_name] = AbstractMethodCheckerCases::eValid; + if (!callable_or_err) { + llvm::consumeError(callable_or_err.takeError()); + SET_CASE_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotAllocated) + } + + PythonCallable callable = callable_or_err->AsType(); + if (!callable) + SET_CASE_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotCallable) + + if (!requirement.min_arg_count) + SET_CASE_AND_CONTINUE(method_name, AbstractMethodCheckerCases::eValid) + + auto arg_info_or_err = callable.GetArgInfo(); + if (!arg_info_or_err) { + llvm::consumeError(arg_info_or_err.takeError()); + SET_CASE_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eUnknownArgumentCount) + } + + PythonCallable::ArgInfo arg_info = *arg_info_or_err; + if (requirement.min_arg_count <= arg_info.max_positional_args) { + SET_CASE_AND_CONTINUE(method_name, AbstractMethodCheckerCases::eValid) + } else { + checker[method_name] = { + AbstractMethodCheckerCases::eInvalidArgumentCount, + AbstrackMethodCheckerPayload::InvalidArgumentCountPayload( + requirement.min_arg_count, arg_info.max_positional_args)}; + } } -#undef HANDLE_ERROR +#undef SET_CASE_AND_CONTINUE return checker; } @@ -78,8 +119,11 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { using namespace python; using Locker = ScriptInterpreterPythonImpl::Locker; - auto create_error = [](std::string message) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), message); + Log *log = GetLog(LLDBLog::Script); + auto create_error = [](llvm::StringLiteral format, auto &&...ts) { + return llvm::createStringError( + llvm::formatv(format.data(), std::forward(ts)...) + .str()); }; bool has_class_name = !class_name.empty(); @@ -107,16 +151,15 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { PythonModule::MainModule().ResolveName( m_interpreter.GetDictionaryName()); if (!dict.IsAllocated()) - return create_error( - llvm::formatv("Could not find interpreter dictionary: %s", - m_interpreter.GetDictionaryName())); + return create_error("Could not find interpreter dictionary: {0}", + m_interpreter.GetDictionaryName()); auto init = PythonObject::ResolveNameWithDictionary( class_name, dict); if (!init.IsAllocated()) - return create_error(llvm::formatv("Could not find script class: {0}", - class_name.data())); + return create_error("Could not find script class: {0}", + class_name.data()); std::tuple original_args = std::forward_as_tuple(args...); auto transformed_args = TransformArgs(original_args); @@ -186,36 +229,73 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { if (!checker_or_err) return checker_or_err.takeError(); + llvm::Error abstract_method_errors = llvm::Error::success(); for (const auto &method_checker : *checker_or_err) - switch (method_checker.second) { + switch (method_checker.second.checker_case) { case AbstractMethodCheckerCases::eNotImplemented: - LLDB_LOG(GetLog(LLDBLog::Script), - "Abstract method {0}.{1} not implemented.", - obj_class_name.GetString(), method_checker.first); + abstract_method_errors = llvm::joinErrors( + std::move(abstract_method_errors), + std::move(create_error("Abstract method {0}.{1} not implemented.", + obj_class_name.GetString(), + method_checker.first))); break; case AbstractMethodCheckerCases::eNotAllocated: - LLDB_LOG(GetLog(LLDBLog::Script), - "Abstract method {0}.{1} not allocated.", - obj_class_name.GetString(), method_checker.first); + abstract_method_errors = llvm::joinErrors( + std::move(abstract_method_errors), + std::move(create_error("Abstract method {0}.{1} not allocated.", + obj_class_name.GetString(), + method_checker.first))); break; case AbstractMethodCheckerCases::eNotCallable: - LLDB_LOG(GetLog(LLDBLog::Script), - "Abstract method {0}.{1} not callable.", - obj_class_name.GetString(), method_checker.first); + abstract_method_errors = llvm::joinErrors( + std::move(abstract_method_errors), + std::move(create_error("Abstract method {0}.{1} not callable.", + obj_class_name.GetString(), + method_checker.first))); + break; + case AbstractMethodCheckerCases::eUnknownArgumentCount: + abstract_method_errors = llvm::joinErrors( + std::move(abstract_method_errors), + std::move(create_error( + "Abstract method {0}.{1} has unknown argument count.", + obj_class_name.GetString(), method_checker.first))); break; + case AbstractMethodCheckerCases::eInvalidArgumentCount: { + auto &payload_variant = method_checker.second.payload; + if (!std::holds_alternative< + AbstrackMethodCheckerPayload::InvalidArgumentCountPayload>( + payload_variant)) { + abstract_method_errors = llvm::joinErrors( + std::move(abstract_method_errors), + std::move(create_error( + "Abstract method {0}.{1} has unexpected argument count.", + obj_class_name.GetString(), method_checker.first))); + } else { + auto payload = std::get< + AbstrackMethodCheckerPayload::InvalidArgumentCountPayload>( + payload_variant); + abstract_method_errors = llvm::joinErrors( + std::move(abstract_method_errors), + std::move( + create_error("Abstract method {0}.{1} has unexpected " + "argument count (expected {2} but has {3}).", + obj_class_name.GetString(), method_checker.first, + payload.required_argument_count, + payload.actual_argument_count))); + } + } break; case AbstractMethodCheckerCases::eValid: - LLDB_LOG(GetLog(LLDBLog::Script), - "Abstract method {0}.{1} implemented & valid.", + LLDB_LOG(log, "Abstract method {0}.{1} implemented & valid.", obj_class_name.GetString(), method_checker.first); break; } - for (const auto &method_checker : *checker_or_err) - if (method_checker.second != AbstractMethodCheckerCases::eValid) - return create_error( - llvm::formatv("Abstract method {0}.{1} missing. Enable lldb " - "script log for more details.", - obj_class_name.GetString(), method_checker.first)); + if (abstract_method_errors) { + Status error = Status::FromError(std::move(abstract_method_errors)); + LLDB_LOG(log, "Abstract method error in {0}:\n{1}", class_name, + error.AsCString()); + return error.ToError(); + } m_object_instance_sp = StructuredData::GenericSP( new StructuredPythonObject(std::move(result))); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h index 5e78ae764eeb5..2d017396df7e2 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h @@ -30,7 +30,8 @@ class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface, lldb::ThreadPlanSP thread_plan_sp, const StructuredDataImpl &args_sp) override; - llvm::SmallVector GetAbstractMethods() const override { + llvm::SmallVector + GetAbstractMethodRequirements() const override { return {}; } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h index 5676f7f1d6752..1fb23b39c7076 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h @@ -28,9 +28,10 @@ class ScriptedThreadPythonInterface : public ScriptedThreadInterface, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; - llvm::SmallVector GetAbstractMethods() const override { - return llvm::SmallVector( - {"get_stop_reason", "get_register_context"}); + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector( + {{"get_stop_reason"}, {"get_register_context"}}); } lldb::tid_t GetThreadID() override; From b651889ebe0750c55001df339e0931732c530658 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Fri, 20 Sep 2024 16:55:47 -0700 Subject: [PATCH 02/15] [lldb/Interpreter] Introduce ScriptedStopHook{,Python}Interface & make use of it (#109498) This patch re-lands #105449 and fixes the various test failures. --------- Signed-off-by: Med Ismail Bennani (cherry picked from commit f732157a9d067e4d300905c831a964222e0eadee) --- lldb/bindings/python/python-swigsafecast.swig | 2 +- lldb/bindings/python/python-wrapper.swig | 111 ++---------------- lldb/include/lldb/API/SBExecutionContext.h | 2 + .../Interfaces/ScriptedStopHookInterface.h | 33 ++++++ .../lldb/Interpreter/ScriptInterpreter.h | 26 ++-- lldb/include/lldb/Target/Target.h | 3 +- lldb/include/lldb/lldb-forward.h | 3 + lldb/source/Interpreter/ScriptInterpreter.cpp | 6 + .../Python/Interfaces/CMakeLists.txt | 1 + .../ScriptInterpreterPythonInterfaces.cpp | 2 + .../ScriptInterpreterPythonInterfaces.h | 1 + .../Interfaces/ScriptedPythonInterface.cpp | 19 +++ .../Interfaces/ScriptedPythonInterface.h | 44 ++++++- .../ScriptedStopHookPythonInterface.cpp | 75 ++++++++++++ .../ScriptedStopHookPythonInterface.h | 51 ++++++++ .../Python/SWIGPythonBridge.h | 13 +- .../Python/ScriptInterpreterPython.cpp | 56 +-------- .../Python/ScriptInterpreterPythonImpl.h | 11 +- lldb/source/Target/Target.cpp | 42 +++++-- .../target/stop-hooks/TestStopHookScripted.py | 4 +- .../dummy_scripted_process.py | 2 +- .../Python/PythonTestSuite.cpp | 21 +--- 22 files changed, 304 insertions(+), 224 deletions(-) create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig index bf139e906704b..6eca207b2f2f8 100644 --- a/lldb/bindings/python/python-swigsafecast.swig +++ b/lldb/bindings/python/python-swigsafecast.swig @@ -37,7 +37,7 @@ PythonObject SWIGBridge::ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp) { SWIGTYPE_p_lldb__SBBreakpoint); } -PythonObject SWIGBridge::ToSWIGWrapper(Status status) { +PythonObject SWIGBridge::ToSWIGWrapper(Status&& status) { return ToSWIGHelper(new lldb::SBError(std::move(status)), SWIGTYPE_p_lldb__SBError); } diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index 5bcce04fc9055..9bd2a9f5db2aa 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -301,104 +301,6 @@ unsigned int lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResol return ret_val; } -PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedStopHook( - lldb::TargetSP target_sp, const char *python_class_name, - const char *session_dictionary_name, const StructuredDataImpl &args_impl, - Status &error) { - if (python_class_name == NULL || python_class_name[0] == '\0') { - error = Status::FromErrorString("Empty class name."); - return PythonObject(); - } - if (!session_dictionary_name) { - error = Status::FromErrorString("No session dictionary"); - return PythonObject(); - } - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = PythonModule::MainModule().ResolveName( - session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary( - python_class_name, dict); - - if (!pfunc.IsAllocated()) { - error = Status::FromErrorStringWithFormat("Could not find class: %s.", - python_class_name); - return PythonObject(); - } - - PythonObject result = - pfunc(SWIGBridge::ToSWIGWrapper(target_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict); - - if (result.IsAllocated()) { - // Check that the handle_stop callback is defined: - auto callback_func = result.ResolveName("handle_stop"); - if (callback_func.IsAllocated()) { - if (auto args_info = callback_func.GetArgInfo()) { - size_t num_args = (*args_info).max_positional_args; - if (num_args != 2) { - error = Status::FromErrorStringWithFormat( - "Wrong number of args for " - "handle_stop callback, should be 2 (excluding self), got: %zu", - num_args); - return PythonObject(); - } else - return result; - } else { - error = Status::FromErrorString( - "Couldn't get num arguments for handle_stop " - "callback."); - return PythonObject(); - } - return result; - } else { - error = Status::FromErrorStringWithFormat( - "Class \"%s\" is missing the required " - "handle_stop callback.", - python_class_name); - } - } - return PythonObject(); -} - -bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop( - void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp, - lldb::StreamSP stream) { - // handle_stop will return a bool with the meaning "should_stop"... - // If you return nothing we'll assume we are going to stop. - // Also any errors should return true, since we should stop on error. - - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName("handle_stop"); - - if (!pfunc.IsAllocated()) - return true; - - std::shared_ptr sb_stream = std::make_shared(); - PythonObject sb_stream_arg = SWIGBridge::ToSWIGWrapper(sb_stream); - PythonObject result = - pfunc(SWIGBridge::ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg); - - if (PyErr_Occurred()) { - stream->PutCString("Python error occurred handling stop-hook."); - PyErr_Print(); - PyErr_Clear(); - return true; - } - - // Now add the result to the output stream. SBStream only - // makes an internally help StreamString which I can't interpose, so I - // have to copy it over here. - stream->PutCString(sb_stream->GetData()); - sb_stream_arg.release(); - - if (result.get() == Py_False) - return false; - else - return true; -} - // wrapper that calls an optional instance member of an object taking no // arguments static PyObject *LLDBSwigPython_CallOptionalMember( @@ -677,6 +579,19 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyOb return sb_ptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject * + data) { + lldb::SBExecutionContext *sb_ptr = NULL; + + int valid_cast = SWIG_ConvertPtr(data, (void **)&sb_ptr, + SWIGTYPE_p_lldb__SBExecutionContext, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommand( const char *python_function_name, const char *session_dictionary_name, lldb::DebuggerSP debugger, const char *args, diff --git a/lldb/include/lldb/API/SBExecutionContext.h b/lldb/include/lldb/API/SBExecutionContext.h index e8de2ebe58785..e1e08fe3f4aae 100644 --- a/lldb/include/lldb/API/SBExecutionContext.h +++ b/lldb/include/lldb/API/SBExecutionContext.h @@ -16,6 +16,7 @@ #include namespace lldb_private { +class ScriptInterpreter; namespace python { class SWIGBridge; } @@ -55,6 +56,7 @@ class LLDB_API SBExecutionContext { protected: friend class lldb_private::python::SWIGBridge; + friend class lldb_private::ScriptInterpreter; lldb_private::ExecutionContextRef *get() const; diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h new file mode 100644 index 0000000000000..a829e62351fe8 --- /dev/null +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h @@ -0,0 +1,33 @@ +//===-- ScriptedStopHookInterface.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H +#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H + +#include "lldb/lldb-private.h" + +#include "ScriptedInterface.h" + +namespace lldb_private { +class ScriptedStopHookInterface : public ScriptedInterface { +public: + virtual llvm::Expected + CreatePluginObject(llvm::StringRef class_name, lldb::TargetSP target_sp, + const StructuredDataImpl &args_sp) = 0; + + /// "handle_stop" will return a bool with the meaning "should_stop"... + /// If nothing is returned, we'll assume we are going to stop. + /// Also any errors should return true, since we should stop on error. + virtual llvm::Expected HandleStop(ExecutionContext &exe_ctx, + lldb::StreamSP &output_sp) { + return true; + } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index e67b179da1dec..25e82779f05c6 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -14,6 +14,7 @@ #include "lldb/API/SBData.h" #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" +#include "lldb/API/SBExecutionContext.h" #include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/API/SBStream.h" @@ -276,24 +277,6 @@ class ScriptInterpreter : public PluginInterface { return lldb::eSearchDepthModule; } - virtual StructuredData::GenericSP - CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, - const StructuredDataImpl &args_data, Status &error) { - error = - Status::FromErrorString("Creating scripted stop-hooks with the current " - "script interpreter is not supported."); - return StructuredData::GenericSP(); - } - - // This dispatches to the handle_stop method of the stop-hook class. It - // returns a "should_stop" bool. - virtual bool - ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, - ExecutionContext &exc_ctx, - lldb::StreamSP stream_sp) { - return true; - } - virtual StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { return StructuredData::ObjectSP(); @@ -581,6 +564,10 @@ class ScriptInterpreter : public PluginInterface { return {}; } + virtual lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() { + return {}; + } + virtual StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) { return {}; @@ -607,6 +594,9 @@ class ScriptInterpreter : public PluginInterface { std::optional GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const; + lldb::ExecutionContextRefSP GetOpaqueTypeFromSBExecutionContext( + const lldb::SBExecutionContext &exe_ctx) const; + protected: Debugger &m_debugger; lldb::ScriptLanguage m_script_lang; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 79df47fec620e..9c3ee0f3259a3 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -1524,8 +1524,7 @@ class Target : public std::enable_shared_from_this, /// This holds the dictionary of keys & values that can be used to /// parametrize any given callback's behavior. StructuredDataImpl m_extra_args; - /// This holds the python callback object. - StructuredData::GenericSP m_implementation_sp; + lldb::ScriptedStopHookInterfaceSP m_interface_sp; /// Use CreateStopHook to make a new empty stop hook. The GetCommandPointer /// and fill it with commands, and SetSpecifier to set the specifier shared diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index d0e7d5e8e2120..7d18c97bfd557 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -190,6 +190,7 @@ class ScriptInterpreterLocker; class ScriptedMetadata; class ScriptedPlatformInterface; class ScriptedProcessInterface; +class ScriptedStopHookInterface; class ScriptedThreadInterface; class ScriptedThreadPlanInterface; class ScriptedSyntheticChildren; @@ -410,6 +411,8 @@ typedef std::unique_ptr ScriptedPlatformInterfaceUP; typedef std::unique_ptr ScriptedProcessInterfaceUP; +typedef std::shared_ptr + ScriptedStopHookInterfaceSP; typedef std::shared_ptr ScriptedThreadInterfaceSP; typedef std::shared_ptr diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 4db95b67e6467..63655cc5a50c6 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -124,6 +124,12 @@ ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo( return *mem_region.m_opaque_up.get(); } +lldb::ExecutionContextRefSP +ScriptInterpreter::GetOpaqueTypeFromSBExecutionContext( + const lldb::SBExecutionContext &exe_ctx) const { + return exe_ctx.m_exe_ctx_sp; +} + lldb::ScriptLanguage ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) { if (language.equals_insensitive(LanguageToString(eScriptLanguageNone))) diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt index 6ba714ed1c263..ee5e48ad5cdc3 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt @@ -25,6 +25,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN ScriptedPlatformPythonInterface.cpp ScriptedProcessPythonInterface.cpp ScriptedPythonInterface.cpp + ScriptedStopHookPythonInterface.cpp ScriptedThreadPlanPythonInterface.cpp ScriptedThreadPythonInterface.cpp diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp index 38b644366080e..1fd32993e385e 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp @@ -28,6 +28,7 @@ void ScriptInterpreterPythonInterfaces::Initialize() { OperatingSystemPythonInterface::Initialize(); ScriptedPlatformPythonInterface::Initialize(); ScriptedProcessPythonInterface::Initialize(); + ScriptedStopHookPythonInterface::Initialize(); ScriptedThreadPlanPythonInterface::Initialize(); } @@ -35,6 +36,7 @@ void ScriptInterpreterPythonInterfaces::Terminate() { OperatingSystemPythonInterface::Terminate(); ScriptedPlatformPythonInterface::Terminate(); ScriptedProcessPythonInterface::Terminate(); + ScriptedStopHookPythonInterface::Terminate(); ScriptedThreadPlanPythonInterface::Terminate(); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h index 36b521480cc85..26c80b7568691 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h @@ -18,6 +18,7 @@ #include "OperatingSystemPythonInterface.h" #include "ScriptedPlatformPythonInterface.h" #include "ScriptedProcessPythonInterface.h" +#include "ScriptedStopHookPythonInterface.h" #include "ScriptedThreadPlanPythonInterface.h" namespace lldb_private { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp index a8e1d09da0bf1..cf11c06e8a95d 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -159,4 +159,23 @@ ScriptedPythonInterface::ExtractValueFromPythonObject< return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info); } +template <> +lldb::ExecutionContextRefSP +ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error) { + + lldb::SBExecutionContext *sb_exe_ctx = + reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(p.get())); + + if (!sb_exe_ctx) { + error = Status::FromErrorStringWithFormat( + "Couldn't cast lldb::SBExecutionContext to " + "lldb::ExecutionContextRefSP."); + return {}; + } + + return m_interpreter.GetOpaqueTypeFromSBExecutionContext(*sb_exe_ctx); +} + #endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h index c715295eb9ff0..4b9f463ef5605 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -180,12 +180,35 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { llvm::Expected expected_return_object = create_error("Resulting object is not initialized."); - std::apply( - [&init, &expected_return_object](auto &&...args) { - llvm::consumeError(expected_return_object.takeError()); - expected_return_object = init(args...); - }, - transformed_args); + // This relax the requirement on the number of argument for + // initializing scripting extension if the size of the interface + // parameter pack contains 1 less element than the extension maximum + // number of positional arguments for this initializer. + // + // This addresses the cases where the embedded interpreter session + // dictionary is passed to the extension initializer which is not used + // most of the time. + size_t num_args = sizeof...(Args); + if (num_args != arg_info->max_positional_args) { + if (num_args != arg_info->max_positional_args - 1) + return create_error("Passed arguments ({0}) doesn't match the number " + "of expected arguments ({1}).", + num_args, arg_info->max_positional_args); + + std::apply( + [&init, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = init(args...); + }, + std::tuple_cat(transformed_args, std::make_tuple(dict))); + } else { + std::apply( + [&init, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = init(args...); + }, + transformed_args); + } if (!expected_return_object) return expected_return_object.takeError(); @@ -405,6 +428,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { return python::SWIGBridge::ToSWIGWrapper(arg); } + python::PythonObject Transform(lldb::TargetSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + python::PythonObject Transform(lldb::ProcessSP arg) { return python::SWIGBridge::ToSWIGWrapper(arg); } @@ -557,6 +584,11 @@ std::optional ScriptedPythonInterface::ExtractValueFromPythonObject< std::optional>(python::PythonObject &p, Status &error); +template <> +lldb::ExecutionContextRefSP +ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error); + } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp new file mode 100644 index 0000000000000..eb052c24bab6d --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.cpp @@ -0,0 +1,75 @@ +//===-- ScriptedStopHookPythonInterface.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/Config.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// clang-format off +// LLDB Python header must be included first +#include "../lldb-python.h" +//clang-format on + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "ScriptedStopHookPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; + +ScriptedStopHookPythonInterface::ScriptedStopHookPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedStopHookInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected +ScriptedStopHookPythonInterface::CreatePluginObject(llvm::StringRef class_name, + lldb::TargetSP target_sp, + const StructuredDataImpl &args_sp) { + return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, + target_sp, args_sp); +} + +llvm::Expected +ScriptedStopHookPythonInterface::HandleStop(ExecutionContext &exe_ctx, + lldb::StreamSP& output_sp) { + ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared(exe_ctx); + Status error; + StructuredData::ObjectSP obj = Dispatch("handle_stop", error, exe_ctx_ref_sp, output_sp); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + if (!obj) + return true; + return error.ToError(); + } + + return obj->GetBooleanValue(); +} + + +void ScriptedStopHookPythonInterface::Initialize() { + const std::vector ci_usages = { + "target stop-hook add -P [-k key -v value ...]"}; + const std::vector api_usages = {}; + PluginManager::RegisterPlugin( + GetPluginNameStatic(), + llvm::StringRef("Perform actions whenever the process stops, before control is returned to the user."), + CreateInstance, eScriptLanguagePython, {ci_usages, api_usages}); +} + +void ScriptedStopHookPythonInterface::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h new file mode 100644 index 0000000000000..7f88098cb7fc7 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedStopHookPythonInterface.h @@ -0,0 +1,51 @@ +//===-- ScriptedStopHookPythonInterface.h -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDSTOPHOOKPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDSTOPHOOKPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" +#include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" + +namespace lldb_private { +class ScriptedStopHookPythonInterface : public ScriptedStopHookInterface, + public ScriptedPythonInterface, + public PluginInterface { +public: + ScriptedStopHookPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(llvm::StringRef class_name, lldb::TargetSP target_sp, + const StructuredDataImpl &args_sp) override; + + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector({{"handle_stop", 2}}); + } + + llvm::Expected HandleStop(ExecutionContext &exe_ctx, + lldb::StreamSP &output_sp) override; + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { + return "ScriptedStopHookPythonInterface"; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDSTOPHOOKPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 677df615609d4..eec29d82b1ed6 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -88,7 +88,7 @@ class SWIGBridge { 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(Status status); + static PythonObject ToSWIGWrapper(Status &&status); static PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl); static PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp); static PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp); @@ -159,16 +159,6 @@ class SWIGBridge { const char *method_name, lldb_private::SymbolContext *sym_ctx); - 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); - - static bool - LLDBSwigPythonStopHookCallHandleStop(void *implementor, - lldb::ExecutionContextRefSP exc_ctx, - lldb::StreamSP stream); - static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor, uint32_t max); @@ -281,6 +271,7 @@ void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data); } // namespace python } // namespace lldb_private diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 3737cd8549257..5c0ec1e8ff0c5 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1565,6 +1565,11 @@ ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() { return std::make_unique(*this); } +ScriptedStopHookInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedStopHookInterface() { + return std::make_shared(*this); +} + ScriptedThreadInterfaceSP ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() { return std::make_shared(*this); @@ -1660,57 +1665,6 @@ ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( return lldb::eSearchDepthModule; } -StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( - TargetSP target_sp, const char *class_name, - const StructuredDataImpl &args_data, Status &error) { - - if (!target_sp) { - error = Status::FromErrorString("No target for scripted stop-hook."); - return StructuredData::GenericSP(); - } - - if (class_name == nullptr || class_name[0] == '\0') { - error = Status::FromErrorString("No class name for scripted stop-hook."); - return StructuredData::GenericSP(); - } - - ScriptInterpreterPythonImpl *python_interpreter = - GetPythonInterpreter(m_debugger); - - if (!python_interpreter) { - error = Status::FromErrorString( - "No script interpreter for scripted stop-hook."); - return StructuredData::GenericSP(); - } - - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - - PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedStopHook( - target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), - args_data, error); - - return StructuredData::GenericSP( - new StructuredPythonObject(std::move(ret_val))); -} - -bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop( - StructuredData::GenericSP implementor_sp, ExecutionContext &exc_ctx, - lldb::StreamSP stream_sp) { - assert(implementor_sp && - "can't call a stop hook with an invalid implementor"); - assert(stream_sp && "can't call a stop hook with an invalid stream"); - - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - - lldb::ExecutionContextRefSP exc_ctx_ref_sp(new ExecutionContextRef(exc_ctx)); - - bool ret_val = SWIGBridge::LLDBSwigPythonStopHookCallHandleStop( - implementor_sp->GetValue(), exc_ctx_ref_sp, stream_sp); - return ret_val; -} - StructuredData::ObjectSP ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 812b44cb66b61..0f2902813397a 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -91,15 +91,6 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { lldb::SearchDepth ScriptedBreakpointResolverSearchDepth( StructuredData::GenericSP implementor_sp) override; - StructuredData::GenericSP - CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, - const StructuredDataImpl &args_data, - Status &error) override; - - bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, - ExecutionContext &exc_ctx, - lldb::StreamSP stream_sp) override; - StructuredData::GenericSP CreateFrameRecognizer(const char *class_name) override; @@ -112,6 +103,8 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override; + lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; lldb::ScriptedThreadPlanInterfaceSP diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 87f9be1b75669..1a93c9535744a 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -36,6 +36,7 @@ #include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h" #include "lldb/Interpreter/OptionGroupWatchpoint.h" #include "lldb/Interpreter/OptionValues.h" #include "lldb/Interpreter/Property.h" @@ -4026,13 +4027,32 @@ Status Target::StopHookScripted::SetScriptCallback( return error; } + m_interface_sp = script_interp->CreateScriptedStopHookInterface(); + if (!m_interface_sp) { + error = Status::FromErrorStringWithFormat( + "ScriptedStopHook::%s () - ERROR: %s", __FUNCTION__, + "Script interpreter couldn't create Scripted Stop Hook Interface"); + return error; + } + m_class_name = class_name; m_extra_args.SetObjectSP(extra_args_sp); - m_implementation_sp = script_interp->CreateScriptedStopHook( - GetTarget(), m_class_name.c_str(), m_extra_args, error); + auto obj_or_err = m_interface_sp->CreatePluginObject( + m_class_name, GetTarget(), m_extra_args); + if (!obj_or_err) { + return Status::FromError(obj_or_err.takeError()); + } - return error; + StructuredData::ObjectSP object_sp = *obj_or_err; + if (!object_sp || !object_sp->IsValid()) { + error = Status::FromErrorStringWithFormat( + "ScriptedStopHook::%s () - ERROR: %s", __FUNCTION__, + "Failed to create valid script object"); + return error; + } + + return {}; } Target::StopHook::StopHookResult @@ -4041,16 +4061,18 @@ Target::StopHookScripted::HandleStop(ExecutionContext &exc_ctx, assert(exc_ctx.GetTargetPtr() && "Can't call HandleStop on a context " "with no target"); - ScriptInterpreter *script_interp = - GetTarget()->GetDebugger().GetScriptInterpreter(); - if (!script_interp) + if (!m_interface_sp) return StopHookResult::KeepStopped; - bool should_stop = script_interp->ScriptedStopHookHandleStop( - m_implementation_sp, exc_ctx, output_sp); + lldb::StreamSP stream = std::make_shared(); + auto should_stop_or_err = m_interface_sp->HandleStop(exc_ctx, stream); + output_sp->PutCString( + reinterpret_cast(stream.get())->GetData()); + if (!should_stop_or_err) + return StopHookResult::KeepStopped; - return should_stop ? StopHookResult::KeepStopped - : StopHookResult::RequestContinue; + return *should_stop_or_err ? StopHookResult::KeepStopped + : StopHookResult::RequestContinue; } void Target::StopHookScripted::GetSubclassDescription( diff --git a/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py b/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py index 583e552bb29f7..b71f3421f9834 100644 --- a/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py +++ b/lldb/test/API/commands/target/stop-hooks/TestStopHookScripted.py @@ -32,7 +32,7 @@ def test_bad_handler(self): self.interp.HandleCommand(command, result) self.assertFalse(result.Succeeded(), "Set the target stop hook") self.assertIn( - "Wrong number of args", + "has unexpected argument count", result.GetError(), "Got the wrong number of args error", ) @@ -43,7 +43,7 @@ def test_bad_handler(self): self.interp.HandleCommand(command, result) self.assertFalse(result.Succeeded(), "Set the target stop hook") self.assertIn( - 'Class "stop_hook.no_handle_stop" is missing the required handle_stop callback', + "Abstract method no_handle_stop.handle_stop not implemented", result.GetError(), "Got the right error", ) diff --git a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py index cb07bf32c5080..2721d961bcb9d 100644 --- a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py @@ -8,7 +8,7 @@ class DummyStopHook: - def __init__(self, target, args, internal_dict): + def __init__(self, target, args): self.target = target self.args = args diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp index ce1d30a5f437f..f7b5e3aeefe17 100644 --- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp @@ -154,6 +154,11 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo( return nullptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBExecutionContext( + PyObject *data) { + return nullptr; +} + lldb::ValueObjectSP lldb_private::python::SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue( void *data) { @@ -288,21 +293,7 @@ void *lldb_private::python::SWIGBridge::LLDBSWIGPython_GetDynamicSetting( } python::PythonObject -lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedStopHook( - lldb::TargetSP target_sp, const char *python_class_name, - const char *session_dictionary_name, const StructuredDataImpl &args_impl, - Status &error) { - return python::PythonObject(); -} - -bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop( - void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp, - lldb::StreamSP stream) { - return false; -} - -python::PythonObject -lldb_private::python::SWIGBridge::ToSWIGWrapper(Status status) { +lldb_private::python::SWIGBridge::ToSWIGWrapper(Status &&status) { return python::PythonObject(); } From 3d8c4dc82fd45413be085d5266ac9a033c501a52 Mon Sep 17 00:00:00 2001 From: oltolm Date: Tue, 25 Feb 2025 00:52:09 +0100 Subject: [PATCH 03/15] [lldb] do not show misleading error when there is no frame (#119103) I am using VSCode with the official vscode-lldb extension. When I try to list the breakpoints in the debug console get the message: ``` br list can't evaluate expressions when the process is running. ``` I know that this is wrong and you need to use ``` `br list (lldb) br list No breakpoints currently set. ``` but the error message is misleading. I cleaned up the code and now the error message is ``` br list sbframe object is not valid. ``` which is still not perfect, but at least it's not misleading. (cherry picked from commit ccbb8882ac75e73e23f31ad60588a2914ebeef04) --- lldb/source/API/SBFrame.cpp | 27 +++++++------------ .../python_api/run_locker/TestRunLocker.py | 4 +-- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 6963da3ce88bf..15c2311adbfa5 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -1013,33 +1013,26 @@ bool SBFrame::GetDescription(SBStream &description) { SBValue SBFrame::EvaluateExpression(const char *expr) { LLDB_INSTRUMENT_VA(this, expr); - SBValue result; std::unique_lock lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock); StackFrame *frame = exe_ctx.GetFramePtr(); Target *target = exe_ctx.GetTargetPtr(); + SBExpressionOptions options; if (frame && target) { - SBExpressionOptions options; lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue(); options.SetFetchDynamicValue(fetch_dynamic_value); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - SourceLanguage language = target->GetLanguage(); - if (!language) - language = frame->GetLanguage(); - options.SetLanguage((SBSourceLanguageName)language.name, language.version); - return EvaluateExpression(expr, options); - } else { - Status error; - error = Status::FromErrorString("can't evaluate expressions when the " - "process is running."); - ValueObjectSP error_val_sp = - ValueObjectConstResult::Create(nullptr, std::move(error)); - result.SetSP(error_val_sp, false); } - return result; + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + SourceLanguage language; + if (target) + language = target->GetLanguage(); + if (!language && frame) + language = frame->GetLanguage(); + options.SetLanguage((SBSourceLanguageName)language.name, language.version); + return EvaluateExpression(expr, options); } SBValue diff --git a/lldb/test/API/python_api/run_locker/TestRunLocker.py b/lldb/test/API/python_api/run_locker/TestRunLocker.py index d525bbf6b406f..b7b4941214e86 100644 --- a/lldb/test/API/python_api/run_locker/TestRunLocker.py +++ b/lldb/test/API/python_api/run_locker/TestRunLocker.py @@ -107,6 +107,4 @@ def runlocker_test(self, stop_at_entry): "script var = lldb.frame.EvaluateExpression('SomethingToCall()'); var.GetError().GetCString()", result, ) - self.assertIn( - "can't evaluate expressions when the process is running", result.GetOutput() - ) + self.assertIn("sbframe object is not valid", result.GetOutput()) From 28a6be5897c897e42f70ef1bd9225a6e3bc860b0 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Wed, 18 Jun 2025 22:49:21 -0700 Subject: [PATCH 04/15] [lldb/crashlog] Make interactive mode the new default (#144839) This patch makes interactive mode as the default when using the crashlog command. It replaces the existing `-i|--interactive` flag with a new `-m|--mode` option, that can either be `interactive` or `batch`. By default, when the option is not explicitely set by the user, the interactive mode is selected, however, lldb will fallback to batch mode if the command interpreter is not interactive or if stdout is not a tty. This also adds some railguards to prevent users from using interactive only options with the batch mode and updates the tests accordingly. rdar://97801509 Differential Revision: https://reviews.llvm.org/D141658 Signed-off-by: Med Ismail Bennani (cherry picked from commit 7b989ade35a43357f9152198ee2c76899df9a56d) --- lldb/examples/python/crashlog.py | 126 +++++++++++------- .../Python/Crashlog/altered_threadState.test | 2 +- .../Python/Crashlog/json.test | 6 +- .../Python/Crashlog/no_threadState.test | 2 +- .../skipped_status_interactive_crashlog.test | 2 +- .../Python/Crashlog/text.test | 2 +- 6 files changed, 85 insertions(+), 55 deletions(-) diff --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py index 741d60d91921c..45756f589b4bf 100755 --- a/lldb/examples/python/crashlog.py +++ b/lldb/examples/python/crashlog.py @@ -31,6 +31,7 @@ import concurrent.futures import contextlib import datetime +import enum import json import os import platform @@ -45,7 +46,6 @@ import time import uuid - print_lock = threading.RLock() try: @@ -1585,9 +1585,12 @@ def synchronous(debugger): debugger.RunCommandInterpreter(True, False, run_options, 0, False, True) -def CreateSymbolicateCrashLogOptions( - command_name, description, add_interactive_options -): +class CrashLogLoadingMode(str, enum.Enum): + batch = "batch" + interactive = "interactive" + + +def CreateSymbolicateCrashLogOptions(command_name, description): usage = "crashlog [options] [FILE ...]" arg_parser = argparse.ArgumentParser( description=description, @@ -1603,6 +1606,12 @@ def CreateSymbolicateCrashLogOptions( help="crash report(s) to symbolicate", ) + arg_parser.add_argument( + "-m", + "--mode", + choices=[mode.value for mode in CrashLogLoadingMode], + help="change how the symbolicated process and threads are displayed to the user (default: interactive)", + ) arg_parser.add_argument( "--version", "-V", @@ -1739,36 +1748,35 @@ def CreateSymbolicateCrashLogOptions( help=argparse.SUPPRESS, default=False, ) - if add_interactive_options: - arg_parser.add_argument( - "-i", - "--interactive", - action="store_true", - help="parse a crash log and load it in a ScriptedProcess", - default=False, - ) - arg_parser.add_argument( - "-b", - "--batch", - action="store_true", - help="dump symbolicated stackframes without creating a debug session", - default=True, - ) - arg_parser.add_argument( - "--target", - "-t", - dest="target_path", - help="the target binary path that should be used for interactive crashlog (optional)", - default=None, - ) - arg_parser.add_argument( - "--skip-status", - "-s", - dest="skip_status", - action="store_true", - help="prevent the interactive crashlog to dump the process status and thread backtrace at launch", - default=False, - ) + arg_parser.add_argument( + "--target", + "-t", + dest="target_path", + help="the target binary path that should be used for interactive crashlog (optional)", + default=None, + ) + arg_parser.add_argument( + "--skip-status", + "-s", + dest="skip_status", + action="store_true", + help="prevent the interactive crashlog to dump the process status and thread backtrace at launch", + default=False, + ) + legacy_group = arg_parser.add_mutually_exclusive_group() + legacy_group.add_argument( + "-i", + "--interactive", + action="store_true", + help=argparse.SUPPRESS, + ) + legacy_group.add_argument( + "-b", + "--batch", + action="store_true", + help=argparse.SUPPRESS, + ) + return arg_parser @@ -1781,7 +1789,7 @@ def CrashLogOptionParser(): created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows you to explore the program as if it were stopped at the locations described in the crash log and functions can be disassembled and lookups can be performed using the addresses found in the crash log.""" - return CreateSymbolicateCrashLogOptions("crashlog", description, True) + return CreateSymbolicateCrashLogOptions("crashlog", description) def SymbolicateCrashLogs(debugger, command_args, result, is_command): @@ -1797,8 +1805,35 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command): result.SetError(str(e)) return + # To avoid breaking existing users, we should keep supporting legacy flags + # even if we don't use them / advertise them anymore. + if not options.mode: + if options.batch: + options.mode = CrashLogLoadingMode.batch + else: + options.mode = CrashLogLoadingMode.interactive + + if options.mode != CrashLogLoadingMode.interactive and ( + options.target_path or options.skip_status + ): + print( + "Target path (-t) and skipping process status (-s) options can only used in interactive mode (-m=interactive)." + ) + print("Aborting symbolication.") + arg_parser.print_help() + return + + if options.version: + print(debugger.GetVersionString()) + return + + if options.debug: + print("command_args = %s" % command_args) + print("options", options) + print("args", options.reports) + # Interactive mode requires running the crashlog command from inside lldb. - if options.interactive and not is_command: + if options.mode == CrashLogLoadingMode.interactive and not is_command: lldb_exec = ( subprocess.check_output(["/usr/bin/xcrun", "-f", "lldb"]) .decode("utf-8") @@ -1824,31 +1859,26 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command): print(debugger.GetVersionString()) return - if options.debug: - print("command_args = %s" % command_args) - print("options", options) - print("args", options.reports) - if options.debug_delay > 0: print("Waiting %u seconds for debugger to attach..." % options.debug_delay) time.sleep(options.debug_delay) error = lldb.SBError() def should_run_in_interactive_mode(options, ci): - if options.interactive: - return True - elif options.batch: + if options.mode == CrashLogLoadingMode.batch: return False - # elif ci and ci.IsInteractive(): - # return True + elif options.mode == CrashLogLoadingMode.interactive or ( + ci and ci.IsInteractive() + ): + return True else: - return False + return sys.stdout.isatty() ci = debugger.GetCommandInterpreter() if options.reports: for crashlog_file in options.reports: - crashlog_path = os.path.expanduser(crashlog_file) + crashlog_path = os.path.normpath(os.path.expanduser(crashlog_file)) if not os.path.exists(crashlog_path): raise FileNotFoundError( "crashlog file %s does not exist" % crashlog_path diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test index 5a946a38b1952..d925324822de7 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test @@ -1,7 +1,7 @@ # RUN: %clang_host -g %S/Inputs/test.c -o %t.out # RUN: cp %S/Inputs/altered_threadState.crash %t.crash # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}' -# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s +# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -b %t.crash' 2>&1 | FileCheck %s # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test index c2e23e82be7f5..d5c6d915316e8 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test @@ -2,12 +2,12 @@ # RUN: cp %S/Inputs/a.out.ips %t.crash # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}' --json -# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s -# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -c %t.crash' 2>&1 | FileCheck %s +# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch %t.crash' 2>&1 | FileCheck %s +# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch -c %t.crash' 2>&1 | FileCheck %s # RUN: cp %S/Inputs/a.out.ips %t.nometadata.crash # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.nometadata.crash --offsets '{"main":20, "bar":9, "foo":16}' --json --no-metadata -# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.nometadata.crash' 2>&1 | FileCheck %s +# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch %t.nometadata.crash' 2>&1 | FileCheck %s # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test index 5b5cef40716ca..2e4b46c8c2409 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test @@ -2,7 +2,7 @@ # RUN: cp %S/Inputs/no_threadState.ips %t.crash # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}' --json -# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s +# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch %t.crash' 2>&1 | FileCheck %s # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test index 64cd0904371aa..52a185b8cf760 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test @@ -3,7 +3,7 @@ # RUN: mkdir -p %t.dir # RUN: yaml2obj %S/Inputs/interactive_crashlog/multithread-test.yaml > %t.dir/multithread-test # RUN: %lldb -b -o 'command script import lldb.macosx.crashlog' \ -# RUN: -o 'crashlog -a -i -s -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.ips' \ +# RUN: -o 'crashlog -a -s -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.ips' \ # RUN: -o 'command source -s 0 %s' 2>&1 | FileCheck %s # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test index e9d1c5e98fb32..eec30a1da64c6 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test @@ -1,7 +1,7 @@ # RUN: %clang_host -g %S/Inputs/test.c -o %t.out # RUN: cp %S/Inputs/a.out.crash %t.crash # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}' -# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s +# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -b %t.crash' 2>&1 | FileCheck %s # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands From 3558a5a6a5dcee77bb25527f28c76b6cc5bdcff9 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Fri, 20 Jun 2025 15:26:14 -0700 Subject: [PATCH 05/15] [lldb/crashlog] Make registers always available & fix x29/x30 parsing (#145104) This patch addresses 2 issues: 1. It makes registers available on non-crashed threads all the time 2. It fixes arm64 registers parsing for registers that don't use the `x` prefix (`fp` -> `x29` / `lr` -> `x30`) --------- Signed-off-by: Med Ismail Bennani (cherry picked from commit 1db9afb102acbb447ee374851d11fcdbea7fe5ec) --- lldb/examples/python/crashlog.py | 8 +- .../python/crashlog_scripted_process.py | 12 +-- .../interactive_crashlog_arm64_register.test | 80 +++++++++++++++++++ 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test diff --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py index 45756f589b4bf..b466be6a62428 100755 --- a/lldb/examples/python/crashlog.py +++ b/lldb/examples/python/crashlog.py @@ -777,10 +777,10 @@ def parse_threads(self, json_threads): if json_thread.get("triggered", False): self.crashlog.crashed_thread_idx = idx thread.crashed = True - if "threadState" in json_thread: - thread.registers = self.parse_thread_registers( - json_thread["threadState"] - ) + if "threadState" in json_thread: + thread.registers = self.parse_thread_registers( + json_thread["threadState"] + ) if "queue" in json_thread: thread.queue = json_thread.get("queue") self.parse_frames(thread, json_thread.get("frames", [])) diff --git a/lldb/examples/python/crashlog_scripted_process.py b/lldb/examples/python/crashlog_scripted_process.py index ddaaf4d744f4f..6c6eec8d12b96 100644 --- a/lldb/examples/python/crashlog_scripted_process.py +++ b/lldb/examples/python/crashlog_scripted_process.py @@ -131,11 +131,6 @@ def get_process_metadata(self): class CrashLogScriptedThread(ScriptedThread): def create_register_ctx(self): - if not self.has_crashed: - return dict.fromkeys( - [*map(lambda reg: reg["name"], self.register_info["registers"])], 0 - ) - if not self.backing_thread or not len(self.backing_thread.registers): return dict.fromkeys( [*map(lambda reg: reg["name"], self.register_info["registers"])], 0 @@ -143,8 +138,15 @@ def create_register_ctx(self): for reg in self.register_info["registers"]: reg_name = reg["name"] + reg_alt_name = None + if "alt-name" in reg: + reg_alt_name = reg["alt-name"] if reg_name in self.backing_thread.registers: self.register_ctx[reg_name] = self.backing_thread.registers[reg_name] + elif reg_alt_name and reg_alt_name in self.backing_thread.registers: + self.register_ctx[reg_name] = self.backing_thread.registers[ + reg_alt_name + ] else: self.register_ctx[reg_name] = 0 diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test new file mode 100644 index 0000000000000..3f572c3300c0f --- /dev/null +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test @@ -0,0 +1,80 @@ +# REQUIRES: python, native && system-darwin + +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/interactive_crashlog/multithread-test.yaml > %t.dir/multithread-test +# RUN: %lldb -o 'command script import lldb.macosx.crashlog' \ +# RUN: -o 'crashlog -a -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.ips' \ +# RUN: -o "thread list" -o "bt all" -o "register read" 2>&1 | FileCheck %s + +# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands + +# CHECK: (lldb) process status +# CHECK-NEXT: Process 22511 stopped +# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) +# CHECK-NEXT: frame #0: 0x0000000100ec58f4 multithread-test`bar + +# CHECK: (lldb) thread backtrace +# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] + +# CHECK: (lldb) thread list +# CHECK-NEXT: Process 22511 stopped +# CHECK-NEXT: thread #1: tid = 0x23c7fe, 0x000000019cc40b84{{.*}}, queue = 'com.apple.main-thread' +# CHECK-NEXT: thread #2: tid = 0x23c800, 0x000000019cc42c9c{{.*}} +# CHECK-NEXT: * thread #3: tid = 0x23c801, 0x0000000100ec58f4 multithread-test`bar{{.*}}, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) + +# CHECK: (lldb) bt all +# CHECK: thread #1, queue = 'com.apple.main-thread' +# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial] +# CHECK-NEXT: thread #2 +# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] + +# CHECK: (lldb) register read +# CHECK: General Purpose Registers: +# CHECK: x0 = 0x000000000000002a +# CHECK: x1 = 0x0000600001d291b0 +# CHECK: x2 = 0x000000019cbbf000 +# CHECK: x3 = 0x0000000000000000 +# CHECK: x4 = 0x00000000000030a0 +# CHECK: x5 = 0x00000000190008ff +# CHECK: x6 = 0x0000000000000000 +# CHECK: x7 = 0x0000000000000000 +# CHECK: x8 = 0x0000000000000001 +# CHECK: x9 = 0x0000000000000000 +# CHECK: x10 = 0xfffffffe634277cf +# CHECK: x11 = 0x0000010000000102 +# CHECK: x12 = 0x0000010000000102 +# CHECK: x13 = 0x0000010000000100 +# CHECK: x14 = 0x0000010000000000 +# CHECK: x15 = 0x0000000000000001 +# CHECK: x16 = 0x000000019cc78ea8 +# CHECK: x17 = 0x00000001fd0a7698 +# CHECK: x18 = 0x0000000000000000 +# CHECK: x19 = 0x000000016f04f000 +# CHECK: x20 = 0x0000000000000000 +# CHECK: x21 = 0x0000000000000000 +# CHECK: x22 = 0x0000000000000000 +# CHECK: x23 = 0x0000000000000000 +# CHECK: x24 = 0x0000000000000000 +# CHECK: x25 = 0x0000000000000000 +# CHECK: x26 = 0x0000000000000000 +# CHECK: x27 = 0x0000000000000000 +# CHECK: x28 = 0x0000000000000000 +# CHECK: x29 = 0x000000016f04ef00 +# CHECK: x30 = 0x0000000100ec591c +# CHECK: sp = 0x000000016f04eee0 +# CHECK: pc = 0x0000000100ec58f4 +# CHECK: cpsr = 0x80001000 From f05bc88fe3b00127d195ac4ebce8e3f99b230b0f Mon Sep 17 00:00:00 2001 From: jimingham Date: Mon, 28 Jul 2025 15:11:22 -0700 Subject: [PATCH 06/15] Switch the ScriptedBreakpointResolver over to the ScriptedInterface form (#150720) This is NFC, I'm modernizing the interface before I add to it in a subsequent commit. (cherry picked from commit 4c8e79f81582a757ed4333f8ff2ad4da18bab39a) --- lldb/bindings/python/python-wrapper.swig | 84 +++------------ lldb/include/lldb/API/SBSymbolContext.h | 2 + .../Breakpoint/BreakpointResolverScripted.h | 4 +- .../Interfaces/ScriptedBreakpointInterface.h | 32 ++++++ .../lldb/Interpreter/ScriptInterpreter.h | 30 ++---- lldb/include/lldb/lldb-forward.h | 3 + .../Breakpoint/BreakpointResolverScripted.cpp | 52 +++++---- lldb/source/Interpreter/ScriptInterpreter.cpp | 7 ++ .../Python/Interfaces/CMakeLists.txt | 1 + .../ScriptInterpreterPythonInterfaces.cpp | 2 + .../ScriptInterpreterPythonInterfaces.h | 1 + .../ScriptedBreakpointPythonInterface.cpp | 100 ++++++++++++++++++ .../ScriptedBreakpointPythonInterface.h | 53 ++++++++++ .../Interfaces/ScriptedPythonInterface.cpp | 15 +++ .../Interfaces/ScriptedPythonInterface.h | 13 +++ .../Python/SWIGPythonBridge.h | 10 +- .../Python/ScriptInterpreterPython.cpp | 74 +------------ .../Python/ScriptInterpreterPythonImpl.h | 14 +-- lldb/source/Target/Target.cpp | 1 + .../scripted_bkpt/TestScriptedResolver.py | 4 +- .../breakpoint/scripted_bkpt/resolver.py | 24 +++++ .../Python/PythonTestSuite.cpp | 19 +--- 22 files changed, 328 insertions(+), 217 deletions(-) create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index 9bd2a9f5db2aa..506d457a40e27 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -229,78 +229,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject return pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger_sp)), dict); } -PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver( - const char *python_class_name, const char *session_dictionary_name, - const StructuredDataImpl &args_impl, - const lldb::BreakpointSP &breakpoint_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( - session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary( - python_class_name, dict); - - if (!pfunc.IsAllocated()) - return PythonObject(); - - PythonObject result = - pfunc(SWIGBridge::ToSWIGWrapper(breakpoint_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict); - // FIXME: At this point we should check that the class we found supports all - // the methods that we need. - - if (result.IsAllocated()) { - // Check that __callback__ is defined: - auto callback_func = result.ResolveName("__callback__"); - if (callback_func.IsAllocated()) - return result; - } - return PythonObject(); -} - -unsigned int lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver( - void *implementor, const char *method_name, - lldb_private::SymbolContext *sym_ctx) { - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName(method_name); - - if (!pfunc.IsAllocated()) - return 0; - - PythonObject result = sym_ctx ? pfunc(SWIGBridge::ToSWIGWrapper(*sym_ctx)) : pfunc(); - - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return 0; - } - - // The callback will return a bool, but we're need to also return ints - // so we're squirrelling the bool through as an int... And if you return - // nothing, we'll continue. - if (strcmp(method_name, "__callback__") == 0) { - if (result.get() == Py_False) - return 0; - else - return 1; - } - - long long ret_val = unwrapOrSetPythonException(As(result)); - - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return 0; - } - - return ret_val; -} - // wrapper that calls an optional instance member of an object taking no // arguments static PyObject *LLDBSwigPython_CallOptionalMember( @@ -554,6 +482,18 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * dat return sb_ptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject * data) { + lldb::SBSymbolContext *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBSymbolContext, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) { lldb::SBValue *sb_ptr = NULL; diff --git a/lldb/include/lldb/API/SBSymbolContext.h b/lldb/include/lldb/API/SBSymbolContext.h index ae9fd8404c5cc..128b0b65b7860 100644 --- a/lldb/include/lldb/API/SBSymbolContext.h +++ b/lldb/include/lldb/API/SBSymbolContext.h @@ -80,6 +80,8 @@ class LLDB_API SBSymbolContext { lldb_private::SymbolContext *get() const; + friend class lldb_private::ScriptInterpreter; + private: std::unique_ptr m_opaque_up; }; diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h b/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h index 16182e36d7095..7544eef3e68de 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h @@ -12,6 +12,7 @@ #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h" #include "lldb/lldb-forward.h" namespace lldb_private { @@ -64,7 +65,8 @@ class BreakpointResolverScripted : public BreakpointResolver { std::string m_class_name; lldb::SearchDepth m_depth; StructuredDataImpl m_args; - StructuredData::GenericSP m_implementation_sp; + Status m_error; + lldb::ScriptedBreakpointInterfaceSP m_interface_sp; BreakpointResolverScripted(const BreakpointResolverScripted &) = delete; const BreakpointResolverScripted & diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h new file mode 100644 index 0000000000000..28d6ed992b141 --- /dev/null +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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_SCRIPTEDBREAKPOINTINTERFACE_H +#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDBREAKPOINTINTERFACE_H + +#include "ScriptedInterface.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { +class ScriptedBreakpointInterface : public ScriptedInterface { +public: + virtual llvm::Expected + CreatePluginObject(llvm::StringRef class_name, lldb::BreakpointSP break_sp, + const StructuredDataImpl &args_sp) = 0; + + /// "ResolverCallback" will get called when a new module is loaded. The + /// new module information is passed in sym_ctx. The Resolver will add + /// any breakpoint locations it found in that module. + virtual bool ResolverCallback(SymbolContext sym_ctx) { return true; } + virtual lldb::SearchDepth GetDepth() { return lldb::eSearchDepthModule; } + virtual std::optional GetShortHelp() { return nullptr; } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 25e82779f05c6..34deeb6c7a39b 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -18,6 +18,7 @@ #include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBSymbolContext.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SearchFilter.h" @@ -29,6 +30,7 @@ #include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h" #include "lldb/Interpreter/ScriptObject.h" +#include "lldb/Symbol/SymbolContext.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" @@ -257,26 +259,6 @@ class ScriptInterpreter : public PluginInterface { return false; } - virtual StructuredData::GenericSP - CreateScriptedBreakpointResolver(const char *class_name, - const StructuredDataImpl &args_data, - lldb::BreakpointSP &bkpt_sp) { - return StructuredData::GenericSP(); - } - - virtual bool - ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp, - SymbolContext *sym_ctx) - { - return false; - } - - virtual lldb::SearchDepth - ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp) - { - return lldb::eSearchDepthModule; - } - virtual StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { return StructuredData::ObjectSP(); @@ -568,6 +550,11 @@ class ScriptInterpreter : public PluginInterface { return {}; } + virtual lldb::ScriptedBreakpointInterfaceSP + CreateScriptedBreakpointInterface() { + return {}; + } + virtual StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) { return {}; @@ -582,6 +569,9 @@ class ScriptInterpreter : public PluginInterface { lldb::StreamSP GetOpaqueTypeFromSBStream(const lldb::SBStream &stream) const; + SymbolContext + GetOpaqueTypeFromSBSymbolContext(const lldb::SBSymbolContext &sym_ctx) const; + lldb::BreakpointSP GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 7d18c97bfd557..319bdef3b8dbd 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -188,6 +188,7 @@ class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; class ScriptedMetadata; +class ScriptedBreakpointInterface; class ScriptedPlatformInterface; class ScriptedProcessInterface; class ScriptedStopHookInterface; @@ -417,6 +418,8 @@ typedef std::shared_ptr ScriptedThreadInterfaceSP; typedef std::shared_ptr ScriptedThreadPlanInterfaceSP; +typedef std::shared_ptr + ScriptedBreakpointInterfaceSP; typedef std::shared_ptr SectionSP; typedef std::unique_ptr SectionListUP; typedef std::weak_ptr SectionWP; diff --git a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp index 2457052ddb6a6..701cabae3ee97 100644 --- a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp @@ -35,7 +35,7 @@ BreakpointResolverScripted::BreakpointResolverScripted( void BreakpointResolverScripted::CreateImplementationIfNeeded( BreakpointSP breakpoint_sp) { - if (m_implementation_sp) + if (m_interface_sp) return; if (m_class_name.empty()) @@ -50,8 +50,27 @@ void BreakpointResolverScripted::CreateImplementationIfNeeded( if (!script_interp) return; - m_implementation_sp = script_interp->CreateScriptedBreakpointResolver( - m_class_name.c_str(), m_args, breakpoint_sp); + m_interface_sp = script_interp->CreateScriptedBreakpointInterface(); + if (!m_interface_sp) { + m_error = Status::FromErrorStringWithFormat( + "BreakpointResolverScripted::%s () - ERROR: %s", __FUNCTION__, + "Script interpreter couldn't create Scripted Breakpoint Interface"); + return; + } + + auto obj_or_err = + m_interface_sp->CreatePluginObject(m_class_name, breakpoint_sp, m_args); + if (!obj_or_err) { + m_error = Status::FromError(obj_or_err.takeError()); + return; + } + + StructuredData::ObjectSP object_sp = *obj_or_err; + if (!object_sp || !object_sp->IsValid()) { + m_error = Status::FromErrorStringWithFormat( + "ScriptedBreakpoint::%s () - ERROR: %s", __FUNCTION__, + "Failed to create valid script object"); + } } void BreakpointResolverScripted::NotifyBreakpointSet() { @@ -104,13 +123,10 @@ ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( SearchFilter &filter, SymbolContext &context, Address *addr) { bool should_continue = true; - if (!m_implementation_sp) + if (!m_interface_sp) return Searcher::eCallbackReturnStop; - ScriptInterpreter *interp = GetScriptInterpreter(); - should_continue = interp->ScriptedBreakpointResolverSearchCallback( - m_implementation_sp, - &context); + should_continue = m_interface_sp->ResolverCallback(context); if (should_continue) return Searcher::eCallbackReturnContinue; @@ -120,25 +136,21 @@ Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( lldb::SearchDepth BreakpointResolverScripted::GetDepth() { lldb::SearchDepth depth = lldb::eSearchDepthModule; - if (m_implementation_sp) { - ScriptInterpreter *interp = GetScriptInterpreter(); - depth = interp->ScriptedBreakpointResolverSearchDepth( - m_implementation_sp); - } + if (m_interface_sp) + depth = m_interface_sp->GetDepth(); + return depth; } void BreakpointResolverScripted::GetDescription(Stream *s) { StructuredData::GenericSP generic_sp; - std::string short_help; + std::optional short_help; - if (m_implementation_sp) { - ScriptInterpreter *interp = GetScriptInterpreter(); - interp->GetShortHelpForCommandObject(m_implementation_sp, - short_help); + if (m_interface_sp) { + short_help = m_interface_sp->GetShortHelp(); } - if (!short_help.empty()) - s->PutCString(short_help.c_str()); + if (short_help && !short_help->empty()) + s->PutCString(short_help->c_str()); else s->Printf("python class = %s", m_class_name.c_str()); } diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 63655cc5a50c6..6b43468c55a65 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -116,6 +116,13 @@ lldb::StreamSP ScriptInterpreter::GetOpaqueTypeFromSBStream( return nullptr; } +SymbolContext ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext( + const lldb::SBSymbolContext &sb_sym_ctx) const { + if (sb_sym_ctx.m_opaque_up) + return *sb_sym_ctx.m_opaque_up.get(); + return {}; +} + std::optional ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt index ee5e48ad5cdc3..29963a334ad94 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt @@ -26,6 +26,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN ScriptedProcessPythonInterface.cpp ScriptedPythonInterface.cpp ScriptedStopHookPythonInterface.cpp + ScriptedBreakpointPythonInterface.cpp ScriptedThreadPlanPythonInterface.cpp ScriptedThreadPythonInterface.cpp diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp index 1fd32993e385e..d43036d6fe544 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp @@ -29,6 +29,7 @@ void ScriptInterpreterPythonInterfaces::Initialize() { ScriptedPlatformPythonInterface::Initialize(); ScriptedProcessPythonInterface::Initialize(); ScriptedStopHookPythonInterface::Initialize(); + ScriptedBreakpointPythonInterface::Initialize(); ScriptedThreadPlanPythonInterface::Initialize(); } @@ -37,6 +38,7 @@ void ScriptInterpreterPythonInterfaces::Terminate() { ScriptedPlatformPythonInterface::Terminate(); ScriptedProcessPythonInterface::Terminate(); ScriptedStopHookPythonInterface::Terminate(); + ScriptedBreakpointPythonInterface::Terminate(); ScriptedThreadPlanPythonInterface::Terminate(); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h index 26c80b7568691..02dc06507caf2 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h @@ -16,6 +16,7 @@ #if LLDB_ENABLE_PYTHON #include "OperatingSystemPythonInterface.h" +#include "ScriptedBreakpointPythonInterface.h" #include "ScriptedPlatformPythonInterface.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedStopHookPythonInterface.h" diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp new file mode 100644 index 0000000000000..660edaa0191f0 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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/Core/PluginManager.h" +#include "lldb/Host/Config.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/Log.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 "ScriptedBreakpointPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; + +ScriptedBreakpointPythonInterface::ScriptedBreakpointPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedBreakpointInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected +ScriptedBreakpointPythonInterface::CreatePluginObject( + llvm::StringRef class_name, lldb::BreakpointSP break_sp, + const StructuredDataImpl &args_sp) { + return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, + break_sp, args_sp); +} + +bool ScriptedBreakpointPythonInterface::ResolverCallback( + SymbolContext sym_ctx) { + Status error; + + StructuredData::ObjectSP obj = Dispatch("__callback__", error, sym_ctx); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + Log *log = GetLog(LLDBLog::Script); + LLDB_LOG(log, "Error calling __callback__ method: {1}", error); + return true; + } + return obj->GetBooleanValue(); +} + +lldb::SearchDepth ScriptedBreakpointPythonInterface::GetDepth() { + Status error; + StructuredData::ObjectSP obj = Dispatch("__get_depth__", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + return lldb::eSearchDepthModule; + } + uint64_t value = obj->GetUnsignedIntegerValue(); + if (value <= lldb::kLastSearchDepthKind) + return (lldb::SearchDepth)value; + // This is what we were doing on error before, though I'm not sure that's + // better than returning eSearchDepthInvalid. + return lldb::eSearchDepthModule; +} + +std::optional ScriptedBreakpointPythonInterface::GetShortHelp() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_short_help", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) { + return {}; + } + + return obj->GetAsString()->GetValue().str(); +} + +void ScriptedBreakpointPythonInterface::Initialize() { + const std::vector ci_usages = { + "breakpoint set -P classname [-k key -v value ...]"}; + const std::vector api_usages = { + "SBTarget.BreakpointCreateFromScript"}; + PluginManager::RegisterPlugin( + GetPluginNameStatic(), + llvm::StringRef("Create a breakpoint that chooses locations based on " + "user-created callbacks"), + CreateInstance, eScriptLanguagePython, {ci_usages, api_usages}); +} + +void ScriptedBreakpointPythonInterface::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h new file mode 100644 index 0000000000000..27bdd8718ac0c --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h @@ -0,0 +1,53 @@ +//===-- ScriptedBreakpointPythonInterface.h -----------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" +#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" + +namespace lldb_private { +class ScriptedBreakpointPythonInterface : public ScriptedBreakpointInterface, + public ScriptedPythonInterface, + public PluginInterface { +public: + ScriptedBreakpointPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(llvm::StringRef class_name, lldb::BreakpointSP break_sp, + const StructuredDataImpl &args_sp) override; + + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector({{"__callback__", 2}}); + } + + bool ResolverCallback(SymbolContext sym_ctx) override; + lldb::SearchDepth GetDepth() override; + std::optional GetShortHelp() override; + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { + return "ScriptedBreakpointPythonInterface"; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp index cf11c06e8a95d..b49d1d82fe535 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -17,6 +17,7 @@ #include "../ScriptInterpreterPythonImpl.h" #include "ScriptedPythonInterface.h" +#include "lldb/Symbol/SymbolContext.h" #include using namespace lldb; @@ -79,6 +80,20 @@ ScriptedPythonInterface::ExtractValueFromPythonObject( return nullptr; } +template <> +SymbolContext +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + if (lldb::SBSymbolContext *sb_symbol_context = + reinterpret_cast( + python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(p.get()))) + return m_interpreter.GetOpaqueTypeFromSBSymbolContext(*sb_symbol_context); + error = Status::FromErrorString( + "Couldn't cast lldb::SBSymbolContext to lldb_private::SymbolContext."); + + return {}; +} + template <> lldb::DataExtractorSP ScriptedPythonInterface::ExtractValueFromPythonObject( diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h index 4b9f463ef5605..b231c202e3c36 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -432,6 +432,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { return python::SWIGBridge::ToSWIGWrapper(arg); } + python::PythonObject Transform(lldb::BreakpointSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + python::PythonObject Transform(lldb::ProcessSP arg) { return python::SWIGBridge::ToSWIGWrapper(arg); } @@ -452,6 +456,10 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { return python::SWIGBridge::ToSWIGWrapper(arg); } + python::PythonObject Transform(const SymbolContext &arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + python::PythonObject Transform(lldb::StreamSP arg) { return python::SWIGBridge::ToSWIGWrapper(arg.get()); } @@ -556,6 +564,11 @@ template <> Event *ScriptedPythonInterface::ExtractValueFromPythonObject( python::PythonObject &p, Status &error); +template <> +SymbolContext +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + template <> lldb::StreamSP ScriptedPythonInterface::ExtractValueFromPythonObject( diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index eec29d82b1ed6..16d18e0b68d52 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -150,15 +150,6 @@ class SWIGBridge { const char *session_dictionary_name, lldb::DebuggerSP debugger_sp); - static python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver( - const char *python_class_name, const char *session_dictionary_name, - const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp); - - static unsigned int - LLDBSwigPythonCallBreakpointResolver(void *implementor, - const char *method_name, - lldb_private::SymbolContext *sym_ctx); - static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor, uint32_t max); @@ -269,6 +260,7 @@ void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 5c0ec1e8ff0c5..402c809201dde 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1570,6 +1570,11 @@ ScriptInterpreterPythonImpl::CreateScriptedStopHookInterface() { return std::make_shared(*this); } +ScriptedBreakpointInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedBreakpointInterface() { + return std::make_shared(*this); +} + ScriptedThreadInterfaceSP ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() { return std::make_shared(*this); @@ -1596,75 +1601,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject( return py_obj.CreateStructuredObject(); } -StructuredData::GenericSP -ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( - const char *class_name, const StructuredDataImpl &args_data, - lldb::BreakpointSP &bkpt_sp) { - - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!bkpt_sp.get()) - return StructuredData::GenericSP(); - - Debugger &debugger = bkpt_sp->GetTarget().GetDebugger(); - ScriptInterpreterPythonImpl *python_interpreter = - GetPythonInterpreter(debugger); - - if (!python_interpreter) - return StructuredData::GenericSP(); - - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - - 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))); -} - -bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback( - StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) { - bool should_continue = false; - - if (implementor_sp) { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_continue = SWIGBridge::LLDBSwigPythonCallBreakpointResolver( - implementor_sp->GetValue(), "__callback__", sym_ctx); - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } - } - return should_continue; -} - -lldb::SearchDepth -ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( - StructuredData::GenericSP implementor_sp) { - int depth_as_int = lldb::eSearchDepthModule; - if (implementor_sp) { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - depth_as_int = SWIGBridge::LLDBSwigPythonCallBreakpointResolver( - implementor_sp->GetValue(), "__get_depth__", nullptr); - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } - } - if (depth_as_int == lldb::eSearchDepthInvalid) - return lldb::eSearchDepthModule; - - if (depth_as_int <= lldb::kLastSearchDepthKind) - return (lldb::SearchDepth)depth_as_int; - return lldb::eSearchDepthModule; -} - StructuredData::ObjectSP ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 0f2902813397a..9845c88636488 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -80,17 +80,6 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) override; - StructuredData::GenericSP - CreateScriptedBreakpointResolver(const char *class_name, - const StructuredDataImpl &args_data, - lldb::BreakpointSP &bkpt_sp) override; - bool ScriptedBreakpointResolverSearchCallback( - StructuredData::GenericSP implementor_sp, - SymbolContext *sym_ctx) override; - - lldb::SearchDepth ScriptedBreakpointResolverSearchDepth( - StructuredData::GenericSP implementor_sp) override; - StructuredData::GenericSP CreateFrameRecognizer(const char *class_name) override; @@ -105,6 +94,9 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override; + lldb::ScriptedBreakpointInterfaceSP + CreateScriptedBreakpointInterface() override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; lldb::ScriptedThreadPlanInterfaceSP diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 1a93c9535744a..0dcb9fe28980e 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -36,6 +36,7 @@ #include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h" #include "lldb/Interpreter/OptionGroupWatchpoint.h" #include "lldb/Interpreter/OptionValues.h" diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py index 0a1003a1b238c..634940dbdc4f9 100644 --- a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py @@ -235,11 +235,13 @@ def do_test_depths(self): substrs=["2"], msg="Was only passed modules", ) - + print(f"Made first breakpoint: {bkpt}") + bkpt = None # Make a breakpoint that asks for modules, check that we didn't get any files: bkpt = target.BreakpointCreateFromScript( "resolver.ResolverModuleDepth", extra_args, module_list, file_list ) + print(f"Made Second breakpoint: {bkpt}") self.assertGreater( bkpt.GetNumLocations(), 0, "ResolverModuleDepth got no locations." ) diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py index 8b91702857481..85c7340127615 100644 --- a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py +++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py @@ -13,6 +13,7 @@ def __init__(self, bkpt, extra_args, dict): Resolver.got_files = 0 def __callback__(self, sym_ctx): + print("Resolver callback called") sym_name = "not_a_real_function_name" sym_item = self.extra_args.GetValueForKey("symbol") if sym_item.IsValid(): @@ -34,9 +35,18 @@ def __callback__(self, sym_ctx): return if sym_ctx.module.IsValid(): + print(f"Looking for {sym_name}") sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode) if sym.IsValid(): + print(f"Adding location at {sym.GetStartAddress()} to {self.bkpt}") self.bkpt.AddLocation(sym.GetStartAddress()) + print(f"After addition: {self.bkpt}") + else: + print("Didn't find it, however...") + + print(f"GotFiles: {Resolver.got_files}") + for func in Resolver.func_list: + print(f"Function: func") def get_short_help(self): return "I am a python breakpoint resolver" @@ -46,17 +56,31 @@ class ResolverModuleDepth(Resolver): def __get_depth__(self): return lldb.eSearchDepthModule + def __callback__(self, sym_ctx): + print(f"About to call the Resolver callback for {self.bkpt}") + Resolver.__callback__(self, sym_ctx) + print("Called the callback for ResolverModuleDepth") + class ResolverCUDepth(Resolver): def __get_depth__(self): return lldb.eSearchDepthCompUnit + def __callback__(self, sym_ctx): + Resolver.__callback__(self, sym_ctx) + class ResolverFuncDepth(Resolver): def __get_depth__(self): return lldb.eSearchDepthFunction + def __callback__(self, sym_ctx): + Resolver.__callback__(self, sym_ctx) + class ResolverBadDepth(Resolver): def __get_depth__(self): return lldb.kLastSearchDepthKind + 1 + + def __callback__(self, sym_ctx): + Resolver.__callback__(self, sym_ctx) diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp index f7b5e3aeefe17..fbb005b3f0fd3 100644 --- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp @@ -80,20 +80,6 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject( return python::PythonObject(); } -python::PythonObject lldb_private::python::SWIGBridge:: - LLDBSwigPythonCreateScriptedBreakpointResolver( - const char *python_class_name, const char *session_dictionary_name, - const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp) { - return python::PythonObject(); -} - -unsigned int -lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver( - void *implementor, const char *method_name, - lldb_private::SymbolContext *sym_ctx) { - return 0; -} - size_t lldb_private::python::SWIGBridge::LLDBSwigPython_CalculateNumChildren( PyObject *implementor, uint32_t max) { return 0; @@ -144,6 +130,11 @@ lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data) { return nullptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext( + PyObject *data) { + return nullptr; +} + void * lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data) { return nullptr; From b3114e3404134a5c8c5a04779d4cbbb3a18a7725 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Mon, 11 Aug 2025 08:27:25 -0700 Subject: [PATCH 07/15] Make StackID call Fix{Code,Data} pointers (#152796) In architectures where pointers may contain metadata, such as arm64e, it is important to ignore those bits when comparing two different StackIDs, as the metadata may not be the same even if the pointers are. This patch is a step towards allowing consumers of pointers to decide whether they want to keep or remove metadata, as opposed to discarding metadata at the moment pointers are created. See https://github.com/llvm/llvm-project/pull/150537. This was tested running the LLDB test suite on arm64e. (cherry picked from commit 9c8e71644227e2a30403dbfe075f96374ba9739c) --- lldb/include/lldb/Target/StackID.h | 12 +++++++----- lldb/source/Target/StackFrame.cpp | 20 +++++++++++++------- lldb/source/Target/StackID.cpp | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/lldb/include/lldb/Target/StackID.h b/lldb/include/lldb/Target/StackID.h index a965c3f6c7225..f1f6063fc1aa2 100644 --- a/lldb/include/lldb/Target/StackID.h +++ b/lldb/include/lldb/Target/StackID.h @@ -14,6 +14,8 @@ namespace lldb_private { +class Process; + class StackID { public: // Constructors and Destructors @@ -21,6 +23,9 @@ class StackID { StackID(const StackID &rhs) = default; + explicit StackID(lldb::addr_t pc, lldb::addr_t cfa, + SymbolContextScope *symbol_scope, Process *process); + ~StackID() = default; lldb::addr_t GetPC() const { return m_pc; } @@ -68,11 +73,8 @@ class StackID { protected: friend class StackFrame; - explicit StackID(lldb::addr_t pc, lldb::addr_t cfa) : m_pc(pc), m_cfa(cfa) {} - - void SetPC(lldb::addr_t pc) { m_pc = pc; } - - void SetCFA(lldb::addr_t cfa) { m_cfa = cfa; } + void SetPC(lldb::addr_t pc, Process *process); + void SetCFA(lldb::addr_t cfa, Process *process); lldb::addr_t m_pc = LLDB_INVALID_ADDRESS; // The pc value for the function/symbol for this diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 1df8b16da8a3d..1530827deab7c 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -64,7 +64,8 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, const SymbolContext *sc_ptr) : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), - m_id(pc, cfa), m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), + m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()), + m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), m_stack_frame_kind(kind), m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), @@ -74,7 +75,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, // recursive functions properly aren't confused with one another on a history // stack. if (IsHistorical() && !m_cfa_is_valid) { - m_id.SetCFA(m_frame_index); + m_id.SetCFA(m_frame_index, thread_sp->GetProcess().get()); } if (sc_ptr != nullptr) { @@ -90,9 +91,11 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, const SymbolContext *sc_ptr) : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), - m_reg_context_sp(reg_context_sp), m_id(pc, cfa), m_frame_code_addr(pc), - m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), - m_cfa_is_valid(true), m_stack_frame_kind(StackFrame::Kind::Regular), + m_reg_context_sp(reg_context_sp), + m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()), + m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), + m_frame_base_error(), m_cfa_is_valid(true), + m_stack_frame_kind(StackFrame::Kind::Regular), m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), m_variable_list_sp(), m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), m_mutex() { @@ -116,7 +119,8 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(reg_context_sp), - m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa), + m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa, + nullptr, thread_sp->GetProcess().get()), m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(true), m_stack_frame_kind(StackFrame::Kind::Regular), @@ -2002,7 +2006,9 @@ void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) { std::lock_guard guard(m_mutex); assert(GetStackID() == curr_frame.GetStackID()); // TODO: remove this after some testing - m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value + m_id.SetPC( + curr_frame.m_id.GetPC(), + curr_frame.CalculateProcess().get()); // Update the Stack ID PC value assert(GetThread() == curr_frame.GetThread()); m_frame_index = curr_frame.m_frame_index; m_concrete_frame_index = curr_frame.m_concrete_frame_index; diff --git a/lldb/source/Target/StackID.cpp b/lldb/source/Target/StackID.cpp index 19989d731d42c..319e1e889f812 100644 --- a/lldb/source/Target/StackID.cpp +++ b/lldb/source/Target/StackID.cpp @@ -32,6 +32,23 @@ bool StackID::IsCFAOnStack(Process &process) const { return m_cfa_on_stack == eLazyBoolYes; } +StackID::StackID(lldb::addr_t pc, lldb::addr_t cfa, + SymbolContextScope *symbol_scope, Process *process) + : m_pc(pc), m_cfa(cfa), m_symbol_scope(symbol_scope) { + if (process) { + m_pc = process->FixCodeAddress(m_pc); + m_cfa = process->FixDataAddress(m_cfa); + } +} + +void StackID::SetPC(lldb::addr_t pc, Process *process) { + m_pc = process ? process->FixCodeAddress(pc) : pc; +} + +void StackID::SetCFA(lldb::addr_t cfa, Process *process) { + m_cfa = process ? process->FixDataAddress(cfa) : cfa; +} + void StackID::Dump(Stream *s) { s->Printf("StackID (pc = 0x%16.16" PRIx64 ", cfa = 0x%16.16" PRIx64 ", cfa_on_stack = %d, symbol_scope = %p", From d511b0e9a3b0292c30aa44dd17cfb31ba2c5122a Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Tue, 2 Sep 2025 14:00:06 -0700 Subject: [PATCH 08/15] Fix StackIDTest compilation issue Commit 9c8e71644227 updated some APIs that are used by this downstream-only test. (cherry picked from commit 5d30e9cd32210082cd6ff95793b36d50c30959ca) --- lldb/unittests/StackID/StackIDTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/unittests/StackID/StackIDTest.cpp b/lldb/unittests/StackID/StackIDTest.cpp index de62f3cd9b4d2..9d5ab45fb8c97 100644 --- a/lldb/unittests/StackID/StackIDTest.cpp +++ b/lldb/unittests/StackID/StackIDTest.cpp @@ -68,8 +68,8 @@ enum OnStack { Yes, No }; /// Helper class to enable testing StackID::IsYounger. struct MockStackID : StackID { MockStackID(addr_t cfa, OnStack on_stack) : StackID() { - SetPC(0); - SetCFA(cfa); + SetPC(0, nullptr); + SetCFA(cfa, nullptr); m_cfa_on_stack = on_stack == OnStack::Yes ? LazyBool::eLazyBoolYes : LazyBool::eLazyBoolNo; } From 9a81ba247c56c0f8e52fea1f8e55a1f95234f968 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Wed, 3 Sep 2025 15:58:14 -0700 Subject: [PATCH 09/15] [lldb] Mark scripted frames as synthetic instead of artificial (#153117) This patch changes the way frames created from scripted affordances like Scripted Threads are displayed. Currently, they're marked artificial which is used usually for compiler generated frames. This patch changes that behaviour by introducing a new synthetic StackFrame kind and moves 'artificial' to be a distinct StackFrame attribut. On top of making these frames less confusing, this allows us to know when a frame was created from a scripted affordance. rdar://155949703 Signed-off-by: Med Ismail Bennani (cherry picked from commit 6c10ab8a3c7b212a73b4ad6673bad02cc34a28c4) --- lldb/include/lldb/API/SBFrame.h | 2 ++ lldb/include/lldb/Core/FormatEntity.h | 1 + lldb/include/lldb/Target/StackFrame.h | 17 +++++++--- lldb/source/API/SBFrame.cpp | 16 ++++++++++ lldb/source/Core/CoreProperties.td | 4 +-- lldb/source/Core/FormatEntity.cpp | 14 ++++++++ .../Process/scripted/ScriptedThread.cpp | 4 ++- lldb/source/Target/StackFrame.cpp | 14 ++++---- lldb/source/Target/StackFrameList.cpp | 6 ++-- .../scripted_process/TestScriptedProcess.py | 2 +- .../app_specific_backtrace_crashlog.test | 32 +++++++++---------- .../interactive_crashlog_arm64_register.test | 30 ++++++++--------- .../Crashlog/interactive_crashlog_json.test | 30 ++++++++--------- .../Crashlog/interactive_crashlog_legacy.test | 30 ++++++++--------- .../last_exception_backtrace_crashlog.test | 32 +++++++++---------- .../skipped_status_interactive_crashlog.test | 30 ++++++++--------- lldb/unittests/Core/FormatEntityTest.cpp | 1 + 17 files changed, 156 insertions(+), 109 deletions(-) diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index d05d2d9cb1afc..33f75f02d9b9e 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -107,6 +107,8 @@ class LLDB_API SBFrame { bool IsArtificial() const; + bool IsSynthetic() const; + /// Return whether a frame recognizer decided this frame should not /// be displayes in backtraces etc. bool IsHidden() const; diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h index d602edffb4c88..40916dc48a70b 100644 --- a/lldb/include/lldb/Core/FormatEntity.h +++ b/lldb/include/lldb/Core/FormatEntity.h @@ -80,6 +80,7 @@ struct Entry { FrameRegisterFlags, FrameRegisterByName, FrameIsArtificial, + FrameKind, ScriptFrame, FunctionID, FunctionDidChange, diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 8b98cf80e8977..a325af126e621 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -60,10 +60,9 @@ class StackFrame : public ExecutionContextScope, /// local variables. History, - /// An artificial stack frame (e.g. a synthesized result of inferring - /// missing tail call frames from a backtrace) with limited support for - /// local variables. - Artificial + /// An synthetic stack frame (e.g. a synthesized result from script + /// resource) possibly without support for local variables or register. + Synthetic }; /// Construct a StackFrame object without supplying a RegisterContextSP. @@ -109,7 +108,8 @@ class StackFrame : public ExecutionContextScope, StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa, bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind, - bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr); + bool artificial, bool behaves_like_zeroth_frame, + const SymbolContext *sc_ptr); StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, @@ -400,6 +400,9 @@ class StackFrame : public ExecutionContextScope, /// true if this is an inlined frame. bool IsInlined(); + /// Query whether this frame is synthetic. + bool IsSynthetic() const; + /// Query whether this frame is part of a historical backtrace. bool IsHistorical() const; @@ -565,6 +568,10 @@ class StackFrame : public ExecutionContextScope, /// Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS. bool m_cfa_is_valid; Kind m_stack_frame_kind; + /// Is this an artificial stack frame (e.g. a synthesized result of inferring + /// missing tail call frames from a backtrace) with limited support for + /// local variables. Orthogonal to `StackFrame::Kind`. + bool m_artificial; /// Whether this frame behaves like the zeroth frame, in the sense /// that its pc value might not immediately follow a call (and thus might diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 15c2311adbfa5..2a1d906522821 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -1208,6 +1208,22 @@ bool SBFrame::IsArtificial() const { return false; } +bool SBFrame::IsSynthetic() const { + LLDB_INSTRUMENT_VA(this); + + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->IsSynthetic(); + + return false; +} + bool SBFrame::IsHidden() const { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index 74119ce41e5ec..0fc5ce02b571e 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -115,7 +115,7 @@ let Definition = "debugger" in { Desc<"The default disassembly format string to use when disassembling instruction sequences.">; def FrameFormat: Property<"frame-format", "FormatEntity">, Global, - DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">, + DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">, Desc<"The default frame format string to use when displaying stack frame information for threads.">; def NotiftVoid: Property<"notify-void", "Boolean">, Global, @@ -271,7 +271,7 @@ let Definition = "debugger" in { Desc<"If true, LLDB will automatically escape non-printable and escape characters when formatting strings.">; def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">, Global, - DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">, + DefaultStringValue<"frame #${frame.index}: ${ansi.fg.cyan}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}${frame.kind}{${function.is-optimized} [opt]}{${function.is-inlined} [inlined]}{${frame.is-artificial} [artificial]}\\\\n">, Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">; def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">, Global, diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index 64e1696279d94..9c321125d3c40 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -108,6 +108,7 @@ constexpr Definition g_frame_child_entries[] = { Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName, g_string_entry), Definition("is-artificial", EntryType::FrameIsArtificial), + Definition("kind", EntryType::FrameKind), }; constexpr Definition g_function_child_entries[] = { @@ -380,6 +381,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) { ENUM_TO_CSTR(FrameRegisterFlags); ENUM_TO_CSTR(FrameRegisterByName); ENUM_TO_CSTR(FrameIsArtificial); + ENUM_TO_CSTR(FrameKind); ENUM_TO_CSTR(ScriptFrame); ENUM_TO_CSTR(FunctionID); ENUM_TO_CSTR(FunctionDidChange); @@ -1757,6 +1759,18 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, return false; } + case Entry::Type::FrameKind: { + if (exe_ctx) + if (StackFrame *frame = exe_ctx->GetFramePtr()) { + if (frame->IsSynthetic()) + s.PutCString(" [synthetic]"); + else if (frame->IsHistorical()) + s.PutCString(" [history]"); + return true; + } + return false; + } + case Entry::Type::ScriptFrame: if (exe_ctx) { StackFrame *frame = exe_ctx->GetFramePtr(); diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp index 88a4ca3b0389f..a2a8c5653d1d5 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -200,13 +200,15 @@ bool ScriptedThread::LoadArtificialStackFrames() { lldb::addr_t cfa = LLDB_INVALID_ADDRESS; bool cfa_is_valid = false; + const bool artificial = false; const bool behaves_like_zeroth_frame = false; SymbolContext sc; symbol_addr.CalculateSymbolContext(&sc); StackFrameSP synth_frame_sp = std::make_shared( this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, - StackFrame::Kind::Artificial, behaves_like_zeroth_frame, &sc); + StackFrame::Kind::Synthetic, artificial, behaves_like_zeroth_frame, + &sc); if (!frames->SetFrameAtIndex(static_cast(idx), synth_frame_sp)) return ScriptedInterface::ErrorWithMessage( diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 1530827deab7c..4fd95bfc52d79 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -60,14 +60,14 @@ using namespace lldb_private; StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, user_id_t unwind_frame_index, addr_t cfa, bool cfa_is_valid, addr_t pc, StackFrame::Kind kind, - bool behaves_like_zeroth_frame, + bool artificial, bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr) : m_thread_wp(thread_sp), m_frame_index(frame_idx), m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(), m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()), m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid), - m_stack_frame_kind(kind), + m_stack_frame_kind(kind), m_artificial(artificial), m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), m_variable_list_sp(), m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), m_mutex() { @@ -95,7 +95,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()), m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(true), - m_stack_frame_kind(StackFrame::Kind::Regular), + m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false), m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), m_variable_list_sp(), m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), m_mutex() { @@ -123,7 +123,7 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx, nullptr, thread_sp->GetProcess().get()), m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(), m_frame_base_error(), m_cfa_is_valid(true), - m_stack_frame_kind(StackFrame::Kind::Regular), + m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false), m_behaves_like_zeroth_frame(behaves_like_zeroth_frame), m_variable_list_sp(), m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(), m_mutex() { @@ -1250,10 +1250,12 @@ bool StackFrame::IsHistorical() const { return m_stack_frame_kind == StackFrame::Kind::History; } -bool StackFrame::IsArtificial() const { - return m_stack_frame_kind == StackFrame::Kind::Artificial; +bool StackFrame::IsSynthetic() const { + return m_stack_frame_kind == StackFrame::Kind::Synthetic; } +bool StackFrame::IsArtificial() const { return m_artificial; } + bool StackFrame::IsHidden() { if (auto recognized_frame_sp = GetRecognizedFrame()) return recognized_frame_sp->ShouldHide(); diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index 4af34a61355da..45e787d1096b6 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -321,13 +321,14 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) { addr_t pc = calleeInfo.address; // If the callee address refers to the call instruction, we do not want to // subtract 1 from this value. + const bool artificial = true; const bool behaves_like_zeroth_frame = calleeInfo.address_type == CallEdge::AddrType::Call; SymbolContext sc; callee->CalculateSymbolContext(&sc); auto synth_frame = std::make_shared( m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa, - cfa_is_valid, pc, StackFrame::Kind::Artificial, + cfa_is_valid, pc, StackFrame::Kind::Regular, artificial, behaves_like_zeroth_frame, &sc); m_frames.push_back(synth_frame); LLDB_LOG(log, "Pushed frame {0} at {1:x}", callee->GetDisplayName(), pc); @@ -470,7 +471,8 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx, const bool cfa_is_valid = true; unwind_frame_sp = std::make_shared( m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid, - pc, StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr); + pc, StackFrame::Kind::Regular, false, behaves_like_zeroth_frame, + nullptr); // Create synthetic tail call frames between the previous frame and the // newly-found frame. The new frame's index may change after this call, diff --git a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py index 9519c576689d0..5916e62c44f2e 100644 --- a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py @@ -284,6 +284,6 @@ def cleanup(): break self.assertEqual(idx, int(reg.value, 16)) - self.assertTrue(frame.IsArtificial(), "Frame is not artificial") + self.assertTrue(frame.IsSynthetic(), "Frame is not synthetic") pc = frame.GetPCAddress().GetLoadAddress(target_0) self.assertEqual(pc, 0x0100001B00) diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/app_specific_backtrace_crashlog.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/app_specific_backtrace_crashlog.test index 9c0510c34ccae..f680158fdf735 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/app_specific_backtrace_crashlog.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/app_specific_backtrace_crashlog.test @@ -11,7 +11,7 @@ # CHECK: (lldb) process status --verbose # CHECK-NEXT: Process 96535 stopped # CHECK-NEXT: * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_CRASH (code=0, subcode=0x0) -# CHECK-NEXT: frame #0: 0x00000001a08c7224{{.*}}[artificial] +# CHECK-NEXT: frame #0: 0x00000001a08c7224{{.*}}[synthetic] # CHECK: Extended Crash Information: # CHECK: Application Specific Information: # CHECK-NEXT: CoreFoundation: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** __boundsFail: index 10 beyond bounds [0 .. 3]' @@ -21,21 +21,21 @@ # CHECK: (lldb) thread backtrace --extended true # CHECK: * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_CRASH (code=0, subcode=0x0) -# CHECK-NEXT: * frame #0: 0x00000001a08c7224{{.*}}[artificial] -# CHECK-NEXT: frame #1: 0x00000001a08fdceb{{.*}}[artificial] -# CHECK-NEXT: frame #2: 0x00000001a08372c7{{.*}}[artificial] -# CHECK-NEXT: frame #3: 0x00000001a08b7b17{{.*}}[artificial] -# CHECK-NEXT: frame #4: 0x00000001a08a7a0b{{.*}}[artificial] -# CHECK-NEXT: frame #5: 0x00000001a05ab763{{.*}}[artificial] -# CHECK-NEXT: frame #6: 0x00000001a08b6eb3{{.*}}[artificial] -# CHECK-NEXT: frame #7: 0x00000001a08b9c2b{{.*}}[artificial] -# CHECK-NEXT: frame #8: 0x00000001a08b9bd7{{.*}}[artificial] -# CHECK-NEXT: frame #9: 0x00000001a05a3007{{.*}}[artificial] -# CHECK-NEXT: frame #10: 0x00000001a0b3dcc3{{.*}}[artificial] -# CHECK-NEXT: frame #11: 0x00000001a0b46af3{{.*}}[artificial] -# CHECK-NEXT: frame #12: 0x00000001a09a12a3{{.*}}[artificial] -# CHECK-NEXT: frame #13: 0x00000001047e3ecf asi`main{{.*}}[artificial] -# CHECK-NEXT: frame #14: 0x00000001a05d3e4f{{.*}}[artificial] +# CHECK-NEXT: * frame #0: 0x00000001a08c7224{{.*}}[synthetic] +# CHECK-NEXT: frame #1: 0x00000001a08fdceb{{.*}}[synthetic] +# CHECK-NEXT: frame #2: 0x00000001a08372c7{{.*}}[synthetic] +# CHECK-NEXT: frame #3: 0x00000001a08b7b17{{.*}}[synthetic] +# CHECK-NEXT: frame #4: 0x00000001a08a7a0b{{.*}}[synthetic] +# CHECK-NEXT: frame #5: 0x00000001a05ab763{{.*}}[synthetic] +# CHECK-NEXT: frame #6: 0x00000001a08b6eb3{{.*}}[synthetic] +# CHECK-NEXT: frame #7: 0x00000001a08b9c2b{{.*}}[synthetic] +# CHECK-NEXT: frame #8: 0x00000001a08b9bd7{{.*}}[synthetic] +# CHECK-NEXT: frame #9: 0x00000001a05a3007{{.*}}[synthetic] +# CHECK-NEXT: frame #10: 0x00000001a0b3dcc3{{.*}}[synthetic] +# CHECK-NEXT: frame #11: 0x00000001a0b46af3{{.*}}[synthetic] +# CHECK-NEXT: frame #12: 0x00000001a09a12a3{{.*}}[synthetic] +# CHECK-NEXT: frame #13: 0x00000001047e3ecf asi`main{{.*}}[synthetic] +# CHECK-NEXT: frame #14: 0x00000001a05d3e4f{{.*}}[synthetic] # CHECK: thread #4294967295: tid = 0x0001, 0x00000001a0a58418{{.*}}, queue = 'Application Specific Backtrace' # CHECK-NEXT: frame #0: 0x00000001a0a58418{{.*}} diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test index 3f572c3300c0f..9da21d9aab78d 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test @@ -15,9 +15,9 @@ # CHECK: (lldb) thread backtrace # CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] # CHECK: (lldb) thread list # CHECK-NEXT: Process 22511 stopped @@ -27,20 +27,20 @@ # CHECK: (lldb) bt all # CHECK: thread #1, queue = 'com.apple.main-thread' -# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [synthetic] # CHECK-NEXT: thread #2 -# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] # CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] # CHECK: (lldb) register read # CHECK: General Purpose Registers: diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test index 684be2846f78d..2509f2e88d9b2 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test @@ -15,9 +15,9 @@ # CHECK: (lldb) thread backtrace # CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] # CHECK: (lldb) thread list # CHECK-NEXT: Process 22511 stopped @@ -27,17 +27,17 @@ # CHECK: (lldb) bt all # CHECK: thread #1, queue = 'com.apple.main-thread' -# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [synthetic] # CHECK-NEXT: thread #2 -# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] # CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test index 271a4c2aa90f4..74ced35fcfae0 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test @@ -15,9 +15,9 @@ # CHECK: (lldb) thread backtrace # CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] # CHECK: (lldb) thread list # CHECK-NEXT: Process 22511 stopped @@ -27,17 +27,17 @@ # CHECK: (lldb) bt all # CHECK: thread #1 -# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [synthetic] # CHECK-NEXT: thread #2 -# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] # CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/last_exception_backtrace_crashlog.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/last_exception_backtrace_crashlog.test index a17b7ac18a620..53c0732deb549 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/last_exception_backtrace_crashlog.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/last_exception_backtrace_crashlog.test @@ -11,7 +11,7 @@ # CHECK: (lldb) process status --verbose # CHECK-NEXT: Process 96535 stopped # CHECK-NEXT: * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_CRASH (code=0, subcode=0x0) -# CHECK-NEXT: frame #0: 0x00000001a08c7224{{.*}}[artificial] +# CHECK-NEXT: frame #0: 0x00000001a08c7224{{.*}}[synthetic] # CHECK: Extended Crash Information: # CHECK: Application Specific Information: # CHECK-NEXT: CoreFoundation: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** __boundsFail: index 10 beyond bounds [0 .. 3]' @@ -21,21 +21,21 @@ # CHECK: (lldb) thread backtrace --extended true # CHECK: * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_CRASH (code=0, subcode=0x0) -# CHECK-NEXT: * frame #0: 0x00000001a08c7224{{.*}}[artificial] -# CHECK-NEXT: frame #1: 0x00000001a08fdceb{{.*}}[artificial] -# CHECK-NEXT: frame #2: 0x00000001a08372c7{{.*}}[artificial] -# CHECK-NEXT: frame #3: 0x00000001a08b7b17{{.*}}[artificial] -# CHECK-NEXT: frame #4: 0x00000001a08a7a0b{{.*}}[artificial] -# CHECK-NEXT: frame #5: 0x00000001a05ab763{{.*}}[artificial] -# CHECK-NEXT: frame #6: 0x00000001a08b6eb3{{.*}}[artificial] -# CHECK-NEXT: frame #7: 0x00000001a08b9c2b{{.*}}[artificial] -# CHECK-NEXT: frame #8: 0x00000001a08b9bd7{{.*}}[artificial] -# CHECK-NEXT: frame #9: 0x00000001a05a3007{{.*}}[artificial] -# CHECK-NEXT: frame #10: 0x00000001a0b3dcc3{{.*}}[artificial] -# CHECK-NEXT: frame #11: 0x00000001a0b46af3{{.*}}[artificial] -# CHECK-NEXT: frame #12: 0x00000001a09a12a3{{.*}}[artificial] -# CHECK-NEXT: frame #13: 0x00000001047e3ecf asi`main{{.*}}[artificial] -# CHECK-NEXT: frame #14: 0x00000001a05d3e4f{{.*}}[artificial] +# CHECK-NEXT: * frame #0: 0x00000001a08c7224{{.*}}[synthetic] +# CHECK-NEXT: frame #1: 0x00000001a08fdceb{{.*}}[synthetic] +# CHECK-NEXT: frame #2: 0x00000001a08372c7{{.*}}[synthetic] +# CHECK-NEXT: frame #3: 0x00000001a08b7b17{{.*}}[synthetic] +# CHECK-NEXT: frame #4: 0x00000001a08a7a0b{{.*}}[synthetic] +# CHECK-NEXT: frame #5: 0x00000001a05ab763{{.*}}[synthetic] +# CHECK-NEXT: frame #6: 0x00000001a08b6eb3{{.*}}[synthetic] +# CHECK-NEXT: frame #7: 0x00000001a08b9c2b{{.*}}[synthetic] +# CHECK-NEXT: frame #8: 0x00000001a08b9bd7{{.*}}[synthetic] +# CHECK-NEXT: frame #9: 0x00000001a05a3007{{.*}}[synthetic] +# CHECK-NEXT: frame #10: 0x00000001a0b3dcc3{{.*}}[synthetic] +# CHECK-NEXT: frame #11: 0x00000001a0b46af3{{.*}}[synthetic] +# CHECK-NEXT: frame #12: 0x00000001a09a12a3{{.*}}[synthetic] +# CHECK-NEXT: frame #13: 0x00000001047e3ecf asi`main{{.*}}[synthetic] +# CHECK-NEXT: frame #14: 0x00000001a05d3e4f{{.*}}[synthetic] # CHECK: thread #4294967295: tid = 0x0001, 0x00000001a0a5840c{{.*}}, queue = 'Application Specific Backtrace' # CHECK-NEXT: frame #0: 0x00000001a0a5840c{{.*}} diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test index 52a185b8cf760..138cd2bdffc44 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test +++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test @@ -15,9 +15,9 @@ process status thread backtrace # CHECK: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] thread list # CHECK: Process 22511 stopped @@ -27,20 +27,20 @@ thread list bt all # CHECK: thread #1, queue = 'com.apple.main-thread' -# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [synthetic] # CHECK-NEXT: thread #2 -# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: frame #0: 0x000000019cc42c9c{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] # CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) -# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial] -# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial] -# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial] -# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial] +# CHECK-NEXT: * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [synthetic] +# CHECK-NEXT: frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [synthetic] +# CHECK-NEXT: frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [synthetic] +# CHECK: frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [synthetic] image list # CHECK: 11111111-2222-3333-4444-555555555555 {{.*}}bogus.dylib diff --git a/lldb/unittests/Core/FormatEntityTest.cpp b/lldb/unittests/Core/FormatEntityTest.cpp index e056b6fe7de52..309294a501883 100644 --- a/lldb/unittests/Core/FormatEntityTest.cpp +++ b/lldb/unittests/Core/FormatEntityTest.cpp @@ -117,6 +117,7 @@ constexpr llvm::StringRef lookupStrings[] = { "${frame.no-debug}", "${frame.reg.*}", "${frame.is-artificial}", + "${frame.kind}", "${function.id}", "${function.name}", "${function.name-without-args}", From 5e593a25846c867aab5f45d6952cac2258e5cc43 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Mon, 4 Aug 2025 09:43:21 -0700 Subject: [PATCH 10/15] [lldb][nfc] Use delegating ctor for ExecutionContext (#151987) The ctor that takes a reference to ExecutionContextRef can be implemented in terms of the ctor that takes a pointer to that object, removing code duplication. (cherry picked from commit 80bd72b9b0d5d1f8fd54a4ee6f8af80734912d5d) --- lldb/include/lldb/Target/ExecutionContext.h | 4 +++- lldb/source/Target/ExecutionContext.cpp | 13 ------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/lldb/include/lldb/Target/ExecutionContext.h b/lldb/include/lldb/Target/ExecutionContext.h index d8c233a666bb4..aebd0d5308e72 100644 --- a/lldb/include/lldb/Target/ExecutionContext.h +++ b/lldb/include/lldb/Target/ExecutionContext.h @@ -318,7 +318,9 @@ class ExecutionContext { // These two variants take in a locker, and grab the target, lock the API // mutex into locker, then fill in the rest of the shared pointers. ExecutionContext(const ExecutionContextRef &exe_ctx_ref, - std::unique_lock &locker); + std::unique_lock &locker) + : ExecutionContext(&exe_ctx_ref, locker) {} + ExecutionContext(const ExecutionContextRef *exe_ctx_ref, std::unique_lock &locker); // Create execution contexts from execution context scopes diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp index b1563d9ceb71b..3f54ea55c9c81 100644 --- a/lldb/source/Target/ExecutionContext.cpp +++ b/lldb/source/Target/ExecutionContext.cpp @@ -140,19 +140,6 @@ ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, } } -ExecutionContext::ExecutionContext(const ExecutionContextRef &exe_ctx_ref, - std::unique_lock &lock) - : m_target_sp(exe_ctx_ref.GetTargetSP()), m_process_sp(), m_thread_sp(), - m_frame_sp() { - if (m_target_sp) { - lock = std::unique_lock(m_target_sp->GetAPIMutex()); - - m_process_sp = exe_ctx_ref.GetProcessSP(); - m_thread_sp = exe_ctx_ref.GetThreadSP(); - m_frame_sp = exe_ctx_ref.GetFrameSP(); - } -} - ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr) : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { if (exe_scope_ptr) From 10c91ff157c09e31248241fc7c99c3de1231241c Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Mon, 4 Aug 2025 09:43:39 -0700 Subject: [PATCH 11/15] [lldb][NFC] Move SBThread::ResumeNewPlan out of the header (#151988) This *private* method is only defined as a member class of SBThread so that it may be declared a `friend` of SBError and access a private constructor of SBError that takes a `Status`, which is an `lldb_private` object. In other words, the method does not use anything about the class is belongs to, so it has no business being a member method. A subsequent patch will need to add a new argument to this class, a `Process::StopLocker`, which is also another `lldb_private` object. This is another strong suggestion that this method does not belong on the header file of a public API, even if at the private visibility level. We can't forward declare nested types like `Process:StopLocker`, so this problem is not easily solvable. This commit moves the method out of the header and into an anon namespace of the cpp file. It is also made to return a Status instead, and the private `SBError` constructor is accessed by the SBThread methods that call it. (cherry picked from commit 849daa4aa05f2b3ac114762c73b9cb48d132a060) --- lldb/include/lldb/API/SBThread.h | 3 --- lldb/source/API/SBThread.cpp | 24 +++++++----------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h index 1ca571a547d60..a53799e7e55c5 100644 --- a/lldb/include/lldb/API/SBThread.h +++ b/lldb/include/lldb/API/SBThread.h @@ -255,9 +255,6 @@ class LLDB_API SBThread { void SetThread(const lldb::ThreadSP &lldb_object_sp); - SBError ResumeNewPlan(lldb_private::ExecutionContext &exe_ctx, - lldb_private::ThreadPlan *new_plan); - lldb::ThreadSP GetSP() const; lldb::ExecutionContextRefSP m_opaque_sp; diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 2d5413fca022a..03bbf3c53b19e 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -514,21 +514,14 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) { return success; } -SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx, - ThreadPlan *new_plan) { - SBError sb_error; - +static Status ResumeNewPlan(ExecutionContext &exe_ctx, ThreadPlan *new_plan) { Process *process = exe_ctx.GetProcessPtr(); - if (!process) { - sb_error = Status::FromErrorString("No process in SBThread::ResumeNewPlan"); - return sb_error; - } + if (!process) + return Status::FromErrorString("No process in SBThread::ResumeNewPlan"); Thread *thread = exe_ctx.GetThreadPtr(); - if (!thread) { - sb_error = Status::FromErrorString("No thread in SBThread::ResumeNewPlan"); - return sb_error; - } + if (!thread) + return Status::FromErrorString("No thread in SBThread::ResumeNewPlan"); // User level plans should be Controlling Plans so they can be interrupted, // other plans executed, and then a "continue" will resume the plan. @@ -541,11 +534,8 @@ SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx, process->GetThreadList().SetSelectedThreadByID(thread->GetID()); if (process->GetTarget().GetDebugger().GetAsyncExecution()) - sb_error.ref() = process->Resume(); - else - sb_error.ref() = process->ResumeSynchronous(nullptr); - - return sb_error; + return process->Resume(); + return process->ResumeSynchronous(nullptr); } void SBThread::StepOver(lldb::RunMode stop_other_threads) { From 0cdd077e3ddc4f678d15b0f9a76e47e3d01db48e Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Thu, 4 Sep 2025 22:46:07 -0700 Subject: [PATCH 12/15] [lldb] Guard SBFrame/SBThread methods against running processes (#152020) Prior to this patch, SBFrame/SBThread methods exhibit racy behavior if called while the process is running, because they do not lock the `Process::RetRunLock` mutex. If they did, they would fail, correctly identifying that the process is not running. Some methods _attempt_ to protect against this with the pattern: ``` ExecutionContext exe_ctx(m_opaque_sp.get(), lock); // this is a different lock Process *process = exe_ctx.GetProcessPtr(); if (process) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) .... do work ... ``` However, this is also racy: the constructor of `ExecutionContext` will access the frame list, which is something that can only be done once the process is stopped. With this patch: 1. The constructor of `ExecutionContext` now expects a `ProcessRunLock` as an argument. It attempts to lock the run lock, and only fills in information about frames and threads if the lock can be acquired. Callers of the constructor are expected to check the lock. 2. All uses of ExecutionContext are adjusted to conform to the above. 3. The SBThread.cpp-defined helper function ResumeNewPlan now expects a locked ProcessRunLock as _proof_ that the execution is stopped. It will unlock the mutex prior to resuming the process. This commit exposes many opportunities for early-returns, but these would increase the diff of this patch and distract from the important changes, so we opt not to do it here. (cherry picked from commit f12e0380be3bd6084ae860090dc027e0281e388e) (cherry picked from commit 057b4b03719d45c388f215a785c29fbad69a976a) Signed-off-by: Med Ismail Bennani --- lldb/include/lldb/API/SBError.h | 1 + lldb/include/lldb/API/SBFrame.h | 4 + lldb/include/lldb/Host/ProcessRunLock.h | 13 + lldb/include/lldb/Target/ExecutionContext.h | 56 +- lldb/source/API/SBFrame.cpp | 910 ++++++++---------- lldb/source/API/SBThread.cpp | 579 ++++++----- lldb/source/Target/ExecutionContext.cpp | 54 +- .../python_api/run_locker/TestRunLocker.py | 4 +- 8 files changed, 840 insertions(+), 781 deletions(-) diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h index 932b544791325..5c521be7ec80c 100644 --- a/lldb/include/lldb/API/SBError.h +++ b/lldb/include/lldb/API/SBError.h @@ -87,6 +87,7 @@ class LLDB_API SBError { friend class SBDebugger; friend class SBFile; friend class SBFormat; + friend class SBFrame; friend class SBHostOS; friend class SBModule; friend class SBPlatform; diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index 33f75f02d9b9e..acd9f3ae3a2bb 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -238,6 +238,10 @@ class LLDB_API SBFrame { void SetFrameSP(const lldb::StackFrameSP &lldb_object_sp); + /// Return an SBValue containing an error message that warns the process is + /// not currently stopped. + static SBValue CreateProcessIsRunningExprEvalError(); + lldb::ExecutionContextRefSP m_opaque_sp; }; diff --git a/lldb/include/lldb/Host/ProcessRunLock.h b/lldb/include/lldb/Host/ProcessRunLock.h index 94683673024d5..27d10942ddb4c 100644 --- a/lldb/include/lldb/Host/ProcessRunLock.h +++ b/lldb/include/lldb/Host/ProcessRunLock.h @@ -41,9 +41,22 @@ class ProcessRunLock { class ProcessRunLocker { public: ProcessRunLocker() = default; + ProcessRunLocker(ProcessRunLocker &&other) : m_lock(other.m_lock) { + other.m_lock = nullptr; + } + ProcessRunLocker &operator=(ProcessRunLocker &&other) { + if (this != &other) { + Unlock(); + m_lock = other.m_lock; + other.m_lock = nullptr; + } + return *this; + } ~ProcessRunLocker() { Unlock(); } + bool IsLocked() const { return m_lock; } + // Try to lock the read lock, but only do so if there are no writers. bool TryLock(ProcessRunLock *lock) { if (m_lock) { diff --git a/lldb/include/lldb/Target/ExecutionContext.h b/lldb/include/lldb/Target/ExecutionContext.h index aebd0d5308e72..a0b064a51cec4 100644 --- a/lldb/include/lldb/Target/ExecutionContext.h +++ b/lldb/include/lldb/Target/ExecutionContext.h @@ -11,6 +11,7 @@ #include +#include "lldb/Host/ProcessRunLock.h" #include "lldb/Target/StackID.h" #include "lldb/lldb-private.h" @@ -315,14 +316,6 @@ class ExecutionContext { ExecutionContext(const ExecutionContextRef *exe_ctx_ref, bool thread_and_frame_only_if_stopped = false); - // These two variants take in a locker, and grab the target, lock the API - // mutex into locker, then fill in the rest of the shared pointers. - ExecutionContext(const ExecutionContextRef &exe_ctx_ref, - std::unique_lock &locker) - : ExecutionContext(&exe_ctx_ref, locker) {} - - ExecutionContext(const ExecutionContextRef *exe_ctx_ref, - std::unique_lock &locker); // Create execution contexts from execution context scopes ExecutionContext(ExecutionContextScope *exe_scope); ExecutionContext(ExecutionContextScope &exe_scope); @@ -566,6 +559,53 @@ class ExecutionContext { lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread. }; +/// A wrapper class representing an execution context with non-null Target +/// and Process pointers, a locked API mutex and a locked ProcessRunLock. +/// The locks are private by design: to unlock them, destroy the +/// StoppedExecutionContext. +struct StoppedExecutionContext : ExecutionContext { + StoppedExecutionContext(lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::ThreadSP &thread_sp, + lldb::StackFrameSP &frame_sp, + std::unique_lock api_lock, + ProcessRunLock::ProcessRunLocker stop_locker) + : m_api_lock(std::move(api_lock)), m_stop_locker(std::move(stop_locker)) { + assert(target_sp); + assert(process_sp); + assert(m_api_lock.owns_lock()); + assert(m_stop_locker.IsLocked()); + SetTargetSP(target_sp); + SetProcessSP(process_sp); + SetThreadSP(thread_sp); + SetFrameSP(frame_sp); + } + + /// Transfers ownership of the locks from `other` to `this`, making `other` + /// unusable. + StoppedExecutionContext(StoppedExecutionContext &&other) + : StoppedExecutionContext(other.m_target_sp, other.m_process_sp, + other.m_thread_sp, other.m_frame_sp, + std::move(other.m_api_lock), + std::move(other.m_stop_locker)) { + other.Clear(); + } + + /// Clears this context, unlocking the ProcessRunLock and returning the + /// locked API lock. Like after a move operation, this object is no longer + /// usable. + [[nodiscard]] std::unique_lock Destroy(); + +private: + std::unique_lock m_api_lock; + ProcessRunLock::ProcessRunLocker m_stop_locker; +}; + +llvm::Expected +GetStoppedExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr); +llvm::Expected +GetStoppedExecutionContext(const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr); + } // namespace lldb_private #endif // LLDB_TARGET_EXECUTIONCONTEXT_H diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 2a1d906522821..3a9d732ed9dec 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -98,226 +98,176 @@ bool SBFrame::IsValid() const { } SBFrame::operator bool() const { LLDB_INSTRUMENT_VA(this); - - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) - return GetFrameSP().get() != nullptr; + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; } - // Without a target & process we can't have a valid stack frame. - return false; + return GetFrameSP().get() != nullptr; } SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const { LLDB_INSTRUMENT_VA(this, resolve_scope); SBSymbolContext sb_sym_ctx; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - SymbolContextItem scope = static_cast(resolve_scope); - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) - sb_sym_ctx = frame->GetSymbolContext(scope); - } + + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_sym_ctx; } + SymbolContextItem scope = static_cast(resolve_scope); + if (StackFrame *frame = exe_ctx->GetFramePtr()) + sb_sym_ctx = frame->GetSymbolContext(scope); + return sb_sym_ctx; } SBModule SBFrame::GetModule() const { LLDB_INSTRUMENT_VA(this); - SBModule sb_module; - ModuleSP module_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp; - sb_module.SetSP(module_sp); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBModule(); } + ModuleSP module_sp; + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return SBModule(); + + SBModule sb_module; + module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp; + sb_module.SetSP(module_sp); return sb_module; } SBCompileUnit SBFrame::GetCompileUnit() const { LLDB_INSTRUMENT_VA(this); - SBCompileUnit sb_comp_unit; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_comp_unit.reset( - frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBCompileUnit(); } - return sb_comp_unit; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBCompileUnit( + frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit); + return SBCompileUnit(); } SBFunction SBFrame::GetFunction() const { LLDB_INSTRUMENT_VA(this); - SBFunction sb_function; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_function.reset( - frame->GetSymbolContext(eSymbolContextFunction).function); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFunction(); } - return sb_function; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBFunction(frame->GetSymbolContext(eSymbolContextFunction).function); + return SBFunction(); } SBSymbol SBFrame::GetSymbol() const { LLDB_INSTRUMENT_VA(this); - SBSymbol sb_symbol; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_symbol.reset(frame->GetSymbolContext(eSymbolContextSymbol).symbol); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBSymbol(); } - return sb_symbol; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBSymbol(frame->GetSymbolContext(eSymbolContextSymbol).symbol); + return SBSymbol(); } SBBlock SBFrame::GetBlock() const { LLDB_INSTRUMENT_VA(this); - SBBlock sb_block; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_block.SetPtr(frame->GetSymbolContext(eSymbolContextBlock).block); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBBlock(); } - return sb_block; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBBlock(frame->GetSymbolContext(eSymbolContextBlock).block); + return SBBlock(); } SBBlock SBFrame::GetFrameBlock() const { LLDB_INSTRUMENT_VA(this); - SBBlock sb_block; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_block.SetPtr(frame->GetFrameBlock()); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBBlock(); } - return sb_block; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBBlock(frame->GetFrameBlock()); + return SBBlock(); } SBLineEntry SBFrame::GetLineEntry() const { LLDB_INSTRUMENT_VA(this); - SBLineEntry sb_line_entry; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - sb_line_entry.SetLineEntry( - frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBLineEntry(); } - return sb_line_entry; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBLineEntry( + &frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); + return SBLineEntry(); } uint32_t SBFrame::GetFrameID() const { LLDB_INSTRUMENT_VA(this); - uint32_t frame_idx = UINT32_MAX; - - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + constexpr uint32_t error_frame_idx = UINT32_MAX; - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) - frame_idx = frame->GetFrameIndex(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return error_frame_idx; + } - return frame_idx; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetFrameIndex(); + return error_frame_idx; } lldb::addr_t SBFrame::GetCFA() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return LLDB_INVALID_ADDRESS; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) + if (StackFrame *frame = exe_ctx->GetFramePtr()) return frame->GetStackID().GetCallFrameAddress(); return LLDB_INVALID_ADDRESS; } @@ -326,114 +276,86 @@ addr_t SBFrame::GetPC() const { LLDB_INSTRUMENT_VA(this); addr_t addr = LLDB_INVALID_ADDRESS; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress( - target, AddressClass::eCode); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return addr; } + Target *target = exe_ctx->GetTargetPtr(); + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetFrameCodeAddress().GetOpcodeLoadAddress( + target, AddressClass::eCode); + return addr; } bool SBFrame::SetPC(addr_t new_pc) { LLDB_INSTRUMENT_VA(this, new_pc); - bool ret_val = false; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { - ret_val = reg_ctx_sp->SetPC(new_pc); - } - } - } + constexpr bool error_ret_val = false; + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return error_ret_val; } - return ret_val; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) + return reg_ctx_sp->SetPC(new_pc); + + return error_ret_val; } addr_t SBFrame::GetSP() const { LLDB_INSTRUMENT_VA(this); - addr_t addr = LLDB_INVALID_ADDRESS; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { - addr = reg_ctx_sp->GetSP(); - } - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return LLDB_INVALID_ADDRESS; } - return addr; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) + return reg_ctx_sp->GetSP(); + + return LLDB_INVALID_ADDRESS; } addr_t SBFrame::GetFP() const { LLDB_INSTRUMENT_VA(this); - addr_t addr = LLDB_INVALID_ADDRESS; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { - addr = reg_ctx_sp->GetFP(); - } - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return LLDB_INVALID_ADDRESS; } - return addr; + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) + return reg_ctx_sp->GetFP(); + + return LLDB_INVALID_ADDRESS; } SBAddress SBFrame::GetPCAddress() const { LLDB_INSTRUMENT_VA(this); - SBAddress sb_addr; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_addr.SetAddress(frame->GetFrameCodeAddress()); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBAddress(); } - return sb_addr; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return SBAddress(frame->GetFrameCodeAddress()); + return SBAddress(); } void SBFrame::Clear() { @@ -446,12 +368,14 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path) { LLDB_INSTRUMENT_VA(this, var_path); SBValue sb_value; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_value; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); sb_value = GetValueForVariablePath(var_path, use_dynamic); @@ -468,27 +392,22 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path, return sb_value; } - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_value; + } - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - VariableSP var_sp; - Status error; - ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath( - var_path, eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, - var_sp, error)); - sb_value.SetSP(value_sp, use_dynamic); - } - } + if (StackFrame *frame = exe_ctx->GetFramePtr()) { + VariableSP var_sp; + Status error; + ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath( + var_path, eNoDynamicValues, + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, + var_sp, error)); + sb_value.SetSP(value_sp, use_dynamic); } return sb_value; } @@ -496,18 +415,19 @@ lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path, SBValue SBFrame::FindVariable(const char *name) { LLDB_INSTRUMENT_VA(this, name); - SBValue value; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValue(); + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); - value = FindVariable(name, use_dynamic); + return FindVariable(name, use_dynamic); } - return value; + return SBValue(); } SBValue SBFrame::FindVariable(const char *name, @@ -521,26 +441,17 @@ SBValue SBFrame::FindVariable(const char *name, return sb_value; } - ValueObjectSP value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - value_sp = frame->FindVariable(ConstString(name)); - - if (value_sp) - sb_value.SetSP(value_sp, use_dynamic); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_value; } + if (StackFrame *frame = exe_ctx->GetFramePtr()) + if (ValueObjectSP value_sp = frame->FindVariable(ConstString(name))) + sb_value.SetSP(value_sp, use_dynamic); + return sb_value; } @@ -548,12 +459,14 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type) { LLDB_INSTRUMENT_VA(this, name, value_type); SBValue value; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return value; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); value = FindValue(name, value_type, use_dynamic); @@ -572,17 +485,17 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type, } ValueObjectSP value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return value_sp; + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { VariableList variable_list; switch (value_type) { @@ -699,10 +612,14 @@ bool SBFrame::operator!=(const SBFrame &rhs) const { SBThread SBFrame::GetThread() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBThread(); + } - ThreadSP thread_sp(exe_ctx.GetThreadSP()); + ThreadSP thread_sp(exe_ctx->GetThreadSP()); SBThread sb_thread(thread_sp); return sb_thread; @@ -711,19 +628,16 @@ SBThread SBFrame::GetThread() const { const char *SBFrame::Disassemble() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (!target || !process) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return nullptr; - - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - if (auto *frame = exe_ctx.GetFramePtr()) - return ConstString(frame->Disassemble()).GetCString(); } + if (auto *frame = exe_ctx->GetFramePtr()) + return ConstString(frame->Disassemble()).GetCString(); + return nullptr; } @@ -732,12 +646,15 @@ SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics, LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only); SBValueList value_list; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return value_list; + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - if (frame && target) { + if (StackFrame *frame = exe_ctx->GetFramePtr()) { + Target *target = exe_ctx->GetTargetPtr(); lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); const bool include_runtime_support_values = @@ -762,12 +679,16 @@ lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals, LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only, use_dynamic); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValueList(); + } - Target *target = exe_ctx.GetTargetPtr(); + Target *target = exe_ctx->GetTargetPtr(); const bool include_runtime_support_values = - target ? target->GetDisplayRuntimeSupportValues() : false; + target->GetDisplayRuntimeSupportValues(); SBVariablesOptions options; options.SetIncludeArguments(arguments); options.SetIncludeLocals(locals); @@ -782,30 +703,26 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { LLDB_INSTRUMENT_VA(this, options); SBValueList value_list; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - - const bool statics = options.GetIncludeStatics(); - const bool arguments = options.GetIncludeArguments(); - const bool recognized_arguments = - options.GetIncludeRecognizedArguments(SBTarget(exe_ctx.GetTargetSP())); - const bool locals = options.GetIncludeLocals(); - const bool in_scope_only = options.GetInScopeOnly(); - const bool include_runtime_support_values = - options.GetIncludeRuntimeSupportValues(); - const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); - + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValueList(); + } else { + const bool statics = options.GetIncludeStatics(); + const bool arguments = options.GetIncludeArguments(); + const bool recognized_arguments = + options.GetIncludeRecognizedArguments(SBTarget(exe_ctx->GetTargetSP())); + const bool locals = options.GetIncludeLocals(); + const bool in_scope_only = options.GetInScopeOnly(); + const bool include_runtime_support_values = + options.GetIncludeRuntimeSupportValues(); + const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); - std::set variable_set; - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + std::set variable_set; + Process *process = exe_ctx->GetProcessPtr(); + if (process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { Debugger &dbg = process->GetTarget().GetDebugger(); VariableList *variable_list = nullptr; Status var_error; @@ -893,17 +810,16 @@ SBValueList SBFrame::GetRegisters() { LLDB_INSTRUMENT_VA(this); SBValueList value_list; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValueList(); + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { RegisterContextSP reg_ctx(frame->GetRegisterContext()); if (reg_ctx) { const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); @@ -924,17 +840,16 @@ SBValue SBFrame::FindRegister(const char *name) { SBValue result; ValueObjectSP value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValue(); + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { RegisterContextSP reg_ctx(frame->GetRegisterContext()); if (reg_ctx) { if (const RegisterInfo *reg_info = @@ -954,12 +869,11 @@ SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, SBStream &output) { Stream &strm = output.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); SBError error; if (!format) { @@ -967,16 +881,9 @@ SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, return error; } - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame && - frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get())) { - return error; - } - } - } + if (StackFrame *frame = exe_ctx->GetFramePtr(); + frame && frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get())) + return error; error.SetErrorStringWithFormat( "It was not possible to generate a frame " "description with the given format string '%s'", @@ -989,23 +896,16 @@ bool SBFrame::GetDescription(SBStream &description) { Stream &strm = description.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - frame->DumpUsingSettingsFormat(&strm); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + strm.PutCString("Error: process is not stopped."); + return true; + } - } else - strm.PutCString("No value"); + if (StackFrame *frame = exe_ctx->GetFramePtr()) + frame->DumpUsingSettingsFormat(&strm); return true; } @@ -1013,22 +913,24 @@ bool SBFrame::GetDescription(SBStream &description) { SBValue SBFrame::EvaluateExpression(const char *expr) { LLDB_INSTRUMENT_VA(this, expr); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return CreateProcessIsRunningExprEvalError(); + } - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); SBExpressionOptions options; - if (frame && target) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue(); options.SetFetchDynamicValue(fetch_dynamic_value); } options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); - SourceLanguage language; - if (target) - language = target->GetLanguage(); + Target *target = exe_ctx->GetTargetPtr(); + SourceLanguage language = target->GetLanguage(); if (!language && frame) language = frame->GetLanguage(); options.SetLanguage((SBSourceLanguageName)language.name, language.version); @@ -1044,14 +946,16 @@ SBFrame::EvaluateExpression(const char *expr, options.SetFetchDynamicValue(fetch_dynamic_value); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - SourceLanguage language; - if (target) - language = target->GetLanguage(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return CreateProcessIsRunningExprEvalError(); + } + + StackFrame *frame = exe_ctx->GetFramePtr(); + Target *target = exe_ctx->GetTargetPtr(); + SourceLanguage language = target->GetLanguage(); if (!language && frame) language = frame->GetLanguage(); options.SetLanguage((SBSourceLanguageName)language.name, language.version); @@ -1064,23 +968,35 @@ SBValue SBFrame::EvaluateExpression(const char *expr, LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value, unwind_on_error); SBExpressionOptions options; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return CreateProcessIsRunningExprEvalError(); + } options.SetFetchDynamicValue(fetch_dynamic_value); options.SetUnwindOnError(unwind_on_error); options.SetIgnoreBreakpoints(true); - StackFrame *frame = exe_ctx.GetFramePtr(); - Target *target = exe_ctx.GetTargetPtr(); - SourceLanguage language; - if (target) - language = target->GetLanguage(); + StackFrame *frame = exe_ctx->GetFramePtr(); + Target *target = exe_ctx->GetTargetPtr(); + SourceLanguage language = target->GetLanguage(); if (!language && frame) language = frame->GetLanguage(); options.SetLanguage((SBSourceLanguageName)language.name, language.version); return EvaluateExpression(expr, options); } +lldb::SBValue SBFrame::CreateProcessIsRunningExprEvalError() { + auto error = Status::FromErrorString("can't evaluate expressions when the " + "process is running."); + ValueObjectSP expr_value_sp = + ValueObjectConstResult::Create(nullptr, std::move(error)); + SBValue expr_result; + expr_result.SetSP(expr_value_sp, false); + return expr_result; +} + lldb::SBValue SBFrame::EvaluateExpression(const char *expr, const SBExpressionOptions &options) { LLDB_INSTRUMENT_VA(this, expr, options); @@ -1095,18 +1011,16 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, ValueObjectSP expr_value_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + expr_result = CreateProcessIsRunningExprEvalError(); + } else { + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + if (target && process) { // FIXME: this check is redundant. + if (StackFrame *frame = exe_ctx->GetFramePtr()) { std::unique_ptr stack_trace; if (target->GetDisplayExpressionsInCrashlogs()) { StreamString frame_description; @@ -1122,17 +1036,11 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); } } else { - Status error; - error = Status::FromErrorString("can't evaluate expressions when the " - "process is running."); - expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error)); - expr_result.SetSP(expr_value_sp, false); - } - } else { Status error; error = Status::FromErrorString("sbframe object is not valid."); expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error)); expr_result.SetSP(expr_value_sp, false); + } } if (expr_result.GetError().Success()) @@ -1153,9 +1061,13 @@ SBStructuredData SBFrame::GetLanguageSpecificData() const { LLDB_INSTRUMENT_VA(this); SBStructuredData sb_data; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - StackFrame *frame = exe_ctx.GetFramePtr(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return sb_data; + } + StackFrame *frame = exe_ctx->GetFramePtr(); if (!frame) return sb_data; @@ -1173,20 +1085,15 @@ bool SBFrame::IsInlined() { bool SBFrame::IsInlined() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - return frame->IsInlined(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; } + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->IsInlined(); return false; } @@ -1199,10 +1106,14 @@ bool SBFrame::IsArtificial() { bool SBFrame::IsArtificial() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (StackFrame *frame = exe_ctx.GetFramePtr()) + if (StackFrame *frame = exe_ctx->GetFramePtr()) return frame->IsArtificial(); return false; @@ -1227,10 +1138,14 @@ bool SBFrame::IsSynthetic() const { bool SBFrame::IsHidden() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (StackFrame *frame = exe_ctx.GetFramePtr()) + if (StackFrame *frame = exe_ctx->GetFramePtr()) return frame->IsHidden(); return false; @@ -1245,38 +1160,36 @@ const char *SBFrame::GetFunctionName() { lldb::LanguageType SBFrame::GuessLanguage() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) { - return frame->GuessLanguage().AsLanguageType(); - } - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return eLanguageTypeUnknown; } + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GuessLanguage().AsLanguageType(); return eLanguageTypeUnknown; } // BEGIN SWIFT bool SBFrame::IsSwiftThunk() const { - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); if (!target || !process) return false; Process::StopLocker stop_locker; if (!stop_locker.TryLock(&process->GetRunLock())) return false; - frame = exe_ctx.GetFramePtr(); + frame = exe_ctx->GetFramePtr(); if (!frame) return false; return frame->IsSwiftThunk(); @@ -1286,42 +1199,29 @@ bool SBFrame::IsSwiftThunk() const { const char *SBFrame::GetFunctionName() const { LLDB_INSTRUMENT_VA(this); - const char *name = nullptr; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - return frame->GetFunctionName(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return nullptr; } - return name; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetFunctionName(); + return nullptr; } const char *SBFrame::GetDisplayFunctionName() { LLDB_INSTRUMENT_VA(this); - const char *name = nullptr; - - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - StackFrame *frame = nullptr; - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - return frame->GetDisplayFunctionName(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return nullptr; } - return name; + + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->GetDisplayFunctionName(); + return nullptr; } diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 03bbf3c53b19e..8dc8b23e83c75 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -90,16 +90,17 @@ lldb::SBQueue SBThread::GetQueue() const { SBQueue sb_queue; QueueSP queue_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - queue_sp = exe_ctx.GetThreadPtr()->GetQueue(); - if (queue_sp) { - sb_queue.SetQueue(queue_sp); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBQueue(); + } + + if (exe_ctx->HasThreadScope()) { + queue_sp = exe_ctx->GetThreadPtr()->GetQueue(); + if (queue_sp) { + sb_queue.SetQueue(queue_sp); } } @@ -112,19 +113,17 @@ bool SBThread::IsValid() const { } SBThread::operator bool() const { LLDB_INSTRUMENT_VA(this); + if (!m_opaque_sp) + return false; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - if (target && process) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&process->GetRunLock())) - return m_opaque_sp->GetThreadSP().get() != nullptr; + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; } - // Without a valid target & process, this thread can't be valid. - return false; + + return m_opaque_sp->GetThreadSP().get() != nullptr; } void SBThread::Clear() { @@ -137,29 +136,27 @@ StopReason SBThread::GetStopReason() { LLDB_INSTRUMENT_VA(this); StopReason reason = eStopReasonInvalid; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - return exe_ctx.GetThreadPtr()->GetStopReason(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return reason; } + if (exe_ctx->HasThreadScope()) + return exe_ctx->GetThreadPtr()->GetStopReason(); + return reason; } size_t SBThread::GetStopReasonDataCount() { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + StopInfoSP stop_info_sp = exe_ctx->GetThreadPtr()->GetStopInfo(); if (stop_info_sp) { StopReason reason = stop_info_sp->GetStopReason(); switch (reason) { @@ -178,7 +175,7 @@ size_t SBThread::GetStopReasonDataCount() { case eStopReasonBreakpoint: { break_id_t site_id = stop_info_sp->GetValue(); lldb::BreakpointSiteSP bp_site_sp( - exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID( + exe_ctx->GetProcessPtr()->GetBreakpointSiteList().FindByID( site_id)); if (bp_site_sp) return bp_site_sp->GetNumberOfConstituents() * 2; @@ -203,6 +200,9 @@ size_t SBThread::GetStopReasonDataCount() { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return 0; } return 0; } @@ -210,13 +210,11 @@ size_t SBThread::GetStopReasonDataCount() { uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - Thread *thread = exe_ctx.GetThreadPtr(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); StopInfoSP stop_info_sp = thread->GetStopInfo(); if (stop_info_sp) { StopReason reason = stop_info_sp->GetStopReason(); @@ -236,7 +234,7 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { case eStopReasonBreakpoint: { break_id_t site_id = stop_info_sp->GetValue(); lldb::BreakpointSiteSP bp_site_sp( - exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID( + exe_ctx->GetProcessPtr()->GetBreakpointSiteList().FindByID( site_id)); if (bp_site_sp) { uint32_t bp_index = idx / 2; @@ -272,6 +270,9 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return 0; } return 0; } @@ -281,13 +282,17 @@ bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) { Stream &strm = stream.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (!exe_ctx.HasThreadScope()) + if (!exe_ctx->HasThreadScope()) return false; - StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo(); + StopInfoSP stop_info = exe_ctx->GetThreadPtr()->GetStopInfo(); StructuredData::ObjectSP info = stop_info->GetExtendedInfo(); if (!info) return false; @@ -303,15 +308,19 @@ SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) { SBThreadCollection threads; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBThreadCollection(); + } - if (!exe_ctx.HasThreadScope()) + if (!exe_ctx->HasThreadScope()) return SBThreadCollection(); - ProcessSP process_sp = exe_ctx.GetProcessSP(); + ProcessSP process_sp = exe_ctx->GetProcessSP(); - StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo(); + StopInfoSP stop_info = exe_ctx->GetThreadPtr()->GetStopInfo(); StructuredData::ObjectSP info = stop_info->GetExtendedInfo(); if (!info) return threads; @@ -324,20 +333,20 @@ SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) { size_t SBThread::GetStopDescription(char *dst, size_t dst_len) { LLDB_INSTRUMENT_VA(this, dst, dst_len); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - if (dst) *dst = 0; - if (!exe_ctx.HasThreadScope()) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return 0; + } - Process::StopLocker stop_locker; - if (!stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) + if (!exe_ctx->HasThreadScope()) return 0; - std::string thread_stop_desc = exe_ctx.GetThreadPtr()->GetStopDescription(); + std::string thread_stop_desc = exe_ctx->GetThreadPtr()->GetStopDescription(); if (thread_stop_desc.empty()) return 0; @@ -378,17 +387,18 @@ SBValue SBThread::GetStopErrorValue() { SBValue SBThread::GetStopReturnOrErrorValue(bool &is_swift_error_value) { LLDB_INSTRUMENT_VA(this, is_swift_error_value); ValueObjectSP return_valobj_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBValue(); + } - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo(); - if (stop_info_sp) { - return_valobj_sp = - StopInfo::GetReturnValueObject(stop_info_sp, is_swift_error_value); - } + if (exe_ctx->HasThreadScope()) { + StopInfoSP stop_info_sp = exe_ctx->GetThreadPtr()->GetStopInfo(); + if (stop_info_sp) { + return_valobj_sp = + StopInfo::GetReturnValueObject(stop_info_sp, is_swift_error_value); } } @@ -421,47 +431,48 @@ uint32_t SBThread::GetIndexID() const { const char *SBThread::GetName() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (!exe_ctx.HasThreadScope()) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return nullptr; + } - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) - return ConstString(exe_ctx.GetThreadPtr()->GetName()).GetCString(); + if (!exe_ctx->HasThreadScope()) + return nullptr; - return nullptr; + return ConstString(exe_ctx->GetThreadPtr()->GetName()).GetCString(); } const char *SBThread::GetQueueName() const { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (!exe_ctx.HasThreadScope()) + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return nullptr; + } - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) - return ConstString(exe_ctx.GetThreadPtr()->GetQueueName()).GetCString(); + if (!exe_ctx->HasThreadScope()) + return nullptr; - return nullptr; + return ConstString(exe_ctx->GetThreadPtr()->GetQueueName()).GetCString(); } lldb::queue_id_t SBThread::GetQueueID() const { LLDB_INSTRUMENT_VA(this); queue_id_t id = LLDB_INVALID_QUEUE_ID; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return id; + } - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - id = exe_ctx.GetThreadPtr()->GetQueueID(); - } + if (exe_ctx->HasThreadScope()) { + id = exe_ctx->GetThreadPtr()->GetQueueID(); } return id; @@ -471,13 +482,11 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) { LLDB_INSTRUMENT_VA(this, path, strm); bool success = false; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - Thread *thread = exe_ctx.GetThreadPtr(); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo(); if (info_root_sp) { StructuredData::ObjectSP node = @@ -509,16 +518,16 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return success; } return success; } -static Status ResumeNewPlan(ExecutionContext &exe_ctx, ThreadPlan *new_plan) { - Process *process = exe_ctx.GetProcessPtr(); - if (!process) - return Status::FromErrorString("No process in SBThread::ResumeNewPlan"); - +static Status ResumeNewPlan(StoppedExecutionContext exe_ctx, + ThreadPlan *new_plan) { Thread *thread = exe_ctx.GetThreadPtr(); if (!thread) return Status::FromErrorString("No thread in SBThread::ResumeNewPlan"); @@ -531,8 +540,11 @@ static Status ResumeNewPlan(ExecutionContext &exe_ctx, ThreadPlan *new_plan) { } // Why do we need to set the current thread by ID here??? + Process *process = exe_ctx.GetProcessPtr(); process->GetThreadList().SetSelectedThreadByID(thread->GetID()); + // Release the run lock but keep the API lock. + std::unique_lock api_lock = exe_ctx.Destroy(); if (process->GetTarget().GetDebugger().GetAsyncExecution()) return process->Resume(); return process->ResumeSynchronous(nullptr); @@ -548,15 +560,19 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads) { void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) { LLDB_INSTRUMENT_VA(this, stop_other_threads, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); bool abort_other_plans = false; StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); @@ -574,7 +590,7 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) { true, abort_other_plans, stop_other_threads, new_plan_status); } } - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); } void SBThread::StepInto(lldb::RunMode stop_other_threads) { @@ -595,17 +611,21 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line, SBError &error, lldb::RunMode stop_other_threads) { LLDB_INSTRUMENT_VA(this, target_name, end_line, error, stop_other_threads); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } bool abort_other_plans = false; - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); ThreadPlanSP new_plan_sp; Status new_plan_status; @@ -634,7 +654,7 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line, } if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -649,10 +669,14 @@ void SBThread::StepOut() { void SBThread::StepOut(SBError &error) { LLDB_INSTRUMENT_VA(this, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } @@ -660,7 +684,7 @@ void SBThread::StepOut(SBError &error) { bool abort_other_plans = false; bool stop_other_threads = false; - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); const LazyBool avoid_no_debug = eLazyBoolCalculate; Status new_plan_status; @@ -669,7 +693,7 @@ void SBThread::StepOut(SBError &error) { eVoteNoOpinion, 0, new_plan_status, avoid_no_debug)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -684,8 +708,12 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame) { void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { LLDB_INSTRUMENT_VA(this, sb_frame, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } if (!sb_frame.IsValid()) { error = Status::FromErrorString("passed invalid SBFrame object"); @@ -694,14 +722,14 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { StackFrameSP frame_sp(sb_frame.GetFrameSP()); - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } bool abort_other_plans = false; bool stop_other_threads = false; - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); if (sb_frame.GetThread().GetThreadID() != thread->GetID()) { error = Status::FromErrorString("passed a frame from another thread"); return; @@ -713,7 +741,7 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -728,21 +756,25 @@ void SBThread::StepInstruction(bool step_over) { void SBThread::StepInstruction(bool step_over, SBError &error) { LLDB_INSTRUMENT_VA(this, step_over, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status new_plan_status; ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction( step_over, false, true, new_plan_status)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -757,10 +789,14 @@ void SBThread::RunToAddress(lldb::addr_t addr) { void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) { LLDB_INSTRUMENT_VA(this, addr, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return; + } - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return; } @@ -770,14 +806,14 @@ void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) { Address target_addr(addr); - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status new_plan_status; ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress( abort_other_plans, target_addr, stop_other_threads, new_plan_status)); if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -789,14 +825,16 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, SBError sb_error; char path[PATH_MAX]; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); StackFrameSP frame_sp(sb_frame.GetFrameSP()); - if (exe_ctx.HasThreadScope()) { - Target *target = exe_ctx.GetTargetPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); + if (exe_ctx->HasThreadScope()) { + Target *target = exe_ctx->GetTargetPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); if (line == 0) { sb_error = Status::FromErrorString("invalid line argument"); @@ -890,7 +928,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, frame_sp->GetFrameIndex(), new_plan_status)); if (new_plan_status.Success()) - sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + sb_error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else sb_error = Status::FromErrorString(new_plan_status.AsCString()); } @@ -922,15 +960,17 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, SBError error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { error = Status::FromErrorString("this SBThread object is invalid"); return error; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status new_plan_status; StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP(); @@ -946,7 +986,7 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name, return error; if (new_plan_status.Success()) - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + error = ResumeNewPlan(std::move(*exe_ctx), new_plan_sp.get()); else error = Status::FromErrorString(new_plan_status.AsCString()); @@ -958,15 +998,17 @@ SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) { SBError sb_error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (!exe_ctx.HasThreadScope()) { + if (!exe_ctx->HasThreadScope()) { sb_error = Status::FromErrorString("this SBThread object is invalid"); return sb_error; } - Thread *thread = exe_ctx.GetThreadPtr(); + Thread *thread = exe_ctx->GetThreadPtr(); Status err = thread->JumpToLine(file_spec.ref(), line, true); sb_error.SetError(std::move(err)); @@ -978,11 +1020,13 @@ SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) { SBError sb_error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (exe_ctx.HasThreadScope()) { - Thread *thread = exe_ctx.GetThreadPtr(); + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); sb_error.SetError( thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP())); } @@ -995,11 +1039,13 @@ SBError SBThread::UnwindInnermostExpression() { SBError sb_error; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) + return Status::FromError(exe_ctx.takeError()); - if (exe_ctx.HasThreadScope()) { - Thread *thread = exe_ctx.GetThreadPtr(); + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); sb_error.SetError(thread->UnwindInnermostExpression()); if (sb_error.Success()) thread->SetSelectedFrameByIndex(0, false); @@ -1018,18 +1064,17 @@ bool SBThread::Suspend() { bool SBThread::Suspend(SBError &error) { LLDB_INSTRUMENT_VA(this, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + error = Status::FromError(exe_ctx.takeError()); + return false; + } bool result = false; - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended); - result = true; - } else { - error = Status::FromErrorString("process is running"); - } + if (exe_ctx->HasThreadScope()) { + exe_ctx->GetThreadPtr()->SetResumeState(eStateSuspended); + result = true; } else error = Status::FromErrorString("this SBThread object is invalid"); return result; @@ -1045,19 +1090,19 @@ bool SBThread::Resume() { bool SBThread::Resume(SBError &error) { LLDB_INSTRUMENT_VA(this, error); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + error = Status::FromErrorString("process is running"); + return false; + } bool result = false; - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - const bool override_suspend = true; - exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend); - result = true; - } else { - error = Status::FromErrorString("process is running"); - } + if (exe_ctx->HasThreadScope()) { + const bool override_suspend = true; + exe_ctx->GetThreadPtr()->SetResumeState(eStateRunning, override_suspend); + result = true; } else error = Status::FromErrorString("this SBThread object is invalid"); return result; @@ -1066,22 +1111,30 @@ bool SBThread::Resume(SBError &error) { bool SBThread::IsSuspended() { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) - return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended; + if (exe_ctx->HasThreadScope()) + return exe_ctx->GetThreadPtr()->GetResumeState() == eStateSuspended; return false; } bool SBThread::IsStopped() { LLDB_INSTRUMENT_VA(this); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) - return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true); + if (exe_ctx->HasThreadScope()) + return StateIsStoppedState(exe_ctx->GetThreadPtr()->GetState(), true); return false; } @@ -1089,13 +1142,17 @@ SBProcess SBThread::GetProcess() { LLDB_INSTRUMENT_VA(this); SBProcess sb_process; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBProcess(); + } - if (exe_ctx.HasThreadScope()) { + if (exe_ctx->HasThreadScope()) { // Have to go up to the target so we can get a shared pointer to our // process... - sb_process.SetSP(exe_ctx.GetProcessSP()); + sb_process.SetSP(exe_ctx->GetProcessSP()); } return sb_process; @@ -1104,34 +1161,33 @@ SBProcess SBThread::GetProcess() { uint32_t SBThread::GetNumFrames() { LLDB_INSTRUMENT_VA(this); - uint32_t num_frames = 0; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount(); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return 0; } - return num_frames; + if (exe_ctx->HasThreadScope()) + return exe_ctx->GetThreadPtr()->GetStackFrameCount(); + + return 0; } SBFrame SBThread::GetFrameAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); SBFrame sb_frame; - StackFrameSP frame_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFrame(); + } - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx); - sb_frame.SetFrameSP(frame_sp); - } + if (exe_ctx->HasThreadScope()) { + StackFrameSP frame_sp = exe_ctx->GetThreadPtr()->GetStackFrameAtIndex(idx); + sb_frame.SetFrameSP(frame_sp); } return sb_frame; @@ -1141,17 +1197,17 @@ lldb::SBFrame SBThread::GetSelectedFrame() { LLDB_INSTRUMENT_VA(this); SBFrame sb_frame; - StackFrameSP frame_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - frame_sp = - exe_ctx.GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame); - sb_frame.SetFrameSP(frame_sp); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFrame(); + } + + if (exe_ctx->HasThreadScope()) { + StackFrameSP frame_sp = + exe_ctx->GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame); + sb_frame.SetFrameSP(frame_sp); } return sb_frame; @@ -1162,18 +1218,19 @@ lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) { SBFrame sb_frame; StackFrameSP frame_sp; - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); - - if (exe_ctx.HasThreadScope()) { - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - Thread *thread = exe_ctx.GetThreadPtr(); - frame_sp = thread->GetStackFrameAtIndex(idx); - if (frame_sp) { - thread->SetSelectedFrame(frame_sp.get()); - sb_frame.SetFrameSP(frame_sp); - } + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return SBFrame(); + } + + if (exe_ctx->HasThreadScope()) { + Thread *thread = exe_ctx->GetThreadPtr(); + frame_sp = thread->GetStackFrameAtIndex(idx); + if (frame_sp) { + thread->SetSelectedFrame(frame_sp.get()); + sb_frame.SetFrameSP(frame_sp); } } @@ -1217,12 +1274,16 @@ bool SBThread::GetStatus(SBStream &status) const { Stream &strm = status.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) { - exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true, - /*show_hidden=*/true); + if (exe_ctx->HasThreadScope()) { + exe_ctx->GetThreadPtr()->GetStatus(strm, 0, 1, 1, true, + /*show_hidden=*/true); } else strm.PutCString("No status"); @@ -1240,11 +1301,15 @@ bool SBThread::GetDescription(SBStream &description, bool stop_format) const { Stream &strm = description.ref(); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return false; + } - if (exe_ctx.HasThreadScope()) { - exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat( + if (exe_ctx->HasThreadScope()) { + exe_ctx->GetThreadPtr()->DumpUsingSettingsFormat( strm, LLDB_INVALID_THREAD_ID, stop_format); } else strm.PutCString("No value"); @@ -1262,11 +1327,15 @@ SBError SBThread::GetDescriptionWithFormat(const SBFormat &format, return error; } - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); + if (!exe_ctx) { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); + return error; + } - if (exe_ctx.HasThreadScope()) { - if (exe_ctx.GetThreadPtr()->DumpUsingFormat( + if (exe_ctx->HasThreadScope()) { + if (exe_ctx->GetThreadPtr()->DumpUsingFormat( strm, LLDB_INVALID_THREAD_ID, format.GetFormatEntrySP().get())) { return error; } @@ -1282,17 +1351,15 @@ SBError SBThread::GetDescriptionWithFormat(const SBFormat &format, SBThread SBThread::GetExtendedBacktraceThread(const char *type) { LLDB_INSTRUMENT_VA(this, type); - std::unique_lock lock; - ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + llvm::Expected exe_ctx = + GetStoppedExecutionContext(m_opaque_sp); SBThread sb_origin_thread; - - Process::StopLocker stop_locker; - if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - if (exe_ctx.HasThreadScope()) { - ThreadSP real_thread(exe_ctx.GetThreadSP()); + if (exe_ctx) { + if (exe_ctx->HasThreadScope()) { + ThreadSP real_thread(exe_ctx->GetThreadSP()); if (real_thread) { ConstString type_const(type); - Process *process = exe_ctx.GetProcessPtr(); + Process *process = exe_ctx->GetProcessPtr(); if (process) { SystemRuntime *runtime = process->GetSystemRuntime(); if (runtime) { @@ -1308,6 +1375,8 @@ SBThread SBThread::GetExtendedBacktraceThread(const char *type) { } } } + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); } return sb_origin_thread; diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp index 3f54ea55c9c81..7dc847e097bf8 100644 --- a/lldb/source/Target/ExecutionContext.cpp +++ b/lldb/source/Target/ExecutionContext.cpp @@ -12,7 +12,9 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/State.h" +#include using namespace lldb_private; @@ -125,19 +127,47 @@ ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, } } -ExecutionContext::ExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr, - std::unique_lock &lock) - : m_target_sp(), m_process_sp(), m_thread_sp(), m_frame_sp() { - if (exe_ctx_ref_ptr) { - m_target_sp = exe_ctx_ref_ptr->GetTargetSP(); - if (m_target_sp) { - lock = std::unique_lock(m_target_sp->GetAPIMutex()); +llvm::Expected +lldb_private::GetStoppedExecutionContext( + const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr) { + return GetStoppedExecutionContext(exe_ctx_ref_ptr.get()); +} - m_process_sp = exe_ctx_ref_ptr->GetProcessSP(); - m_thread_sp = exe_ctx_ref_ptr->GetThreadSP(); - m_frame_sp = exe_ctx_ref_ptr->GetFrameSP(); - } - } +llvm::Expected +lldb_private::GetStoppedExecutionContext( + const ExecutionContextRef *exe_ctx_ref_ptr) { + if (!exe_ctx_ref_ptr) + return llvm::createStringError( + "ExecutionContext created with an empty ExecutionContextRef"); + + lldb::TargetSP target_sp = exe_ctx_ref_ptr->GetTargetSP(); + if (!target_sp) + return llvm::createStringError( + "ExecutionContext created with a null target"); + + auto api_lock = + std::unique_lock(target_sp->GetAPIMutex()); + + auto process_sp = exe_ctx_ref_ptr->GetProcessSP(); + if (!process_sp) + return llvm::createStringError( + "ExecutionContext created with a null process"); + + ProcessRunLock::ProcessRunLocker stop_locker; + if (!stop_locker.TryLock(&process_sp->GetRunLock())) + return llvm::createStringError( + "attempted to create an ExecutionContext with a running process"); + + auto thread_sp = exe_ctx_ref_ptr->GetThreadSP(); + auto frame_sp = exe_ctx_ref_ptr->GetFrameSP(); + return StoppedExecutionContext(target_sp, process_sp, thread_sp, frame_sp, + std::move(api_lock), std::move(stop_locker)); +} + +std::unique_lock StoppedExecutionContext::Destroy() { + Clear(); + m_stop_locker = ProcessRunLock::ProcessRunLocker(); + return std::move(m_api_lock); } ExecutionContext::ExecutionContext(ExecutionContextScope *exe_scope_ptr) diff --git a/lldb/test/API/python_api/run_locker/TestRunLocker.py b/lldb/test/API/python_api/run_locker/TestRunLocker.py index b7b4941214e86..d525bbf6b406f 100644 --- a/lldb/test/API/python_api/run_locker/TestRunLocker.py +++ b/lldb/test/API/python_api/run_locker/TestRunLocker.py @@ -107,4 +107,6 @@ def runlocker_test(self, stop_at_entry): "script var = lldb.frame.EvaluateExpression('SomethingToCall()'); var.GetError().GetCString()", result, ) - self.assertIn("sbframe object is not valid", result.GetOutput()) + self.assertIn( + "can't evaluate expressions when the process is running", result.GetOutput() + ) From 2eee7cebdf0fcfb8efc30959eeb5d5dd4696bd92 Mon Sep 17 00:00:00 2001 From: David Spickett Date: Tue, 12 Aug 2025 10:48:08 +0000 Subject: [PATCH 13/15] [lldb][test] Remove a Windows xfail from TestThreadStates This case is passing since https://github.com/llvm/llvm-project/pull/152020. (cherry picked from commit 52f7cfb5ef0a21173f0c7ae2305c76e1662831c5) --- lldb/test/API/functionalities/thread/state/TestThreadStates.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/test/API/functionalities/thread/state/TestThreadStates.py b/lldb/test/API/functionalities/thread/state/TestThreadStates.py index 4dbe230c0ce85..6eeff07955733 100644 --- a/lldb/test/API/functionalities/thread/state/TestThreadStates.py +++ b/lldb/test/API/functionalities/thread/state/TestThreadStates.py @@ -30,7 +30,6 @@ def test_state_after_breakpoint(self): @expectedFailureAll( oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr23669" ) - @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660") def test_state_after_continue(self): """Test thread state after continue.""" self.build() From 1e6108d477e87e5a97266c4159222435c6055588 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Thu, 4 Sep 2025 16:01:33 -0700 Subject: [PATCH 14/15] [lldb] Introduce ScriptedFrame affordance (#149622) This patch introduces a new scripting affordance in lldb: `ScriptedFrame`. This allows user to produce mock stackframes in scripted threads and scripted processes from a python script. With this change, StackFrame can be synthetized from different sources: - Either from a dictionary containing a load address, and a frame index, which is the legacy way. - Or by creating a ScriptedFrame python object. One particularity of synthezising stackframes from the ScriptedFrame python object, is that these frame have an optional PC, meaning that they don't have a report a valid PC and they can act as shells that just contain static information, like the frame function name, the list of variables or registers, etc. It can also provide a symbol context. rdar://157260006 (cherry picked from commit 84b56202fbe150e06f92c855107489e08cc17bcd) Signed-off-by: Med Ismail Bennani --- .../python/templates/scripted_process.py | 136 +++++++++++++ lldb/include/lldb/API/SBSymbolContext.h | 1 + .../Interfaces/ScriptedFrameInterface.h | 55 +++++ .../Interfaces/ScriptedThreadInterface.h | 10 + .../lldb/Interpreter/ScriptInterpreter.h | 5 + lldb/include/lldb/Target/StackFrame.h | 24 ++- lldb/include/lldb/lldb-forward.h | 3 + lldb/source/Core/FormatEntity.cpp | 2 +- .../Plugins/Process/scripted/CMakeLists.txt | 1 + .../Process/scripted/ScriptedFrame.cpp | 191 ++++++++++++++++++ .../Plugins/Process/scripted/ScriptedFrame.h | 63 ++++++ .../Process/scripted/ScriptedThread.cpp | 82 +++++++- .../Plugins/Process/scripted/ScriptedThread.h | 5 +- .../Python/Interfaces/CMakeLists.txt | 1 + .../ScriptInterpreterPythonInterfaces.h | 1 + .../ScriptedFramePythonInterface.cpp | 157 ++++++++++++++ .../Interfaces/ScriptedFramePythonInterface.h | 59 ++++++ .../Interfaces/ScriptedPythonInterface.cpp | 3 +- .../ScriptedThreadPythonInterface.cpp | 17 ++ .../ScriptedThreadPythonInterface.h | 5 + .../Python/ScriptInterpreterPython.cpp | 5 + .../Python/ScriptInterpreterPythonImpl.h | 2 + .../dummy_scripted_process.py | 65 +++++- 23 files changed, 871 insertions(+), 22 deletions(-) create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h create mode 100644 lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp create mode 100644 lldb/source/Plugins/Process/scripted/ScriptedFrame.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h diff --git a/lldb/examples/python/templates/scripted_process.py b/lldb/examples/python/templates/scripted_process.py index c7d5b28b52c00..00f617fc1bbc3 100644 --- a/lldb/examples/python/templates/scripted_process.py +++ b/lldb/examples/python/templates/scripted_process.py @@ -383,6 +383,142 @@ def get_extended_info(self): """ return self.extended_info + def get_scripted_frame_plugin(self): + """Get scripted frame plugin name. + + Returns: + str: Name of the scripted frame plugin. + """ + return None + + +class ScriptedFrame(metaclass=ABCMeta): + """ + The base class for a scripted frame. + + Most of the base class methods are `@abstractmethod` that need to be + overwritten by the inheriting class. + """ + + @abstractmethod + def __init__(self, thread, args): + """Construct a scripted frame. + + Args: + thread (ScriptedThread): The thread owning this frame. + args (lldb.SBStructuredData): A Dictionary holding arbitrary + key/value pairs used by the scripted frame. + """ + self.target = None + self.originating_thread = None + self.thread = None + self.args = None + self.id = None + self.name = None + self.register_info = None + self.register_ctx = {} + self.variables = [] + + if ( + isinstance(thread, ScriptedThread) + or isinstance(thread, lldb.SBThread) + and thread.IsValid() + ): + self.target = thread.target + self.process = thread.process + self.originating_thread = thread + self.thread = self.process.GetThreadByIndexID(thread.tid) + self.get_register_info() + + @abstractmethod + def get_id(self): + """Get the scripted frame identifier. + + Returns: + int: The identifier of the scripted frame in the scripted thread. + """ + pass + + def get_pc(self): + """Get the scripted frame address. + + Returns: + int: The optional address of the scripted frame in the scripted thread. + """ + return None + + def get_symbol_context(self): + """Get the scripted frame symbol context. + + Returns: + lldb.SBSymbolContext: The symbol context of the scripted frame in the scripted thread. + """ + return None + + def is_inlined(self): + """Check if the scripted frame is inlined. + + Returns: + bool: True if scripted frame is inlined. False otherwise. + """ + return False + + def is_artificial(self): + """Check if the scripted frame is artificial. + + Returns: + bool: True if scripted frame is artificial. False otherwise. + """ + return True + + def is_hidden(self): + """Check if the scripted frame is hidden. + + Returns: + bool: True if scripted frame is hidden. False otherwise. + """ + return False + + def get_function_name(self): + """Get the scripted frame function name. + + Returns: + str: The function name of the scripted frame. + """ + return self.name + + def get_display_function_name(self): + """Get the scripted frame display function name. + + Returns: + str: The display function name of the scripted frame. + """ + return self.get_function_name() + + def get_variables(self, filters): + """Get the scripted thread state type. + + Args: + filter (lldb.SBVariablesOptions): The filter used to resolve the variables + Returns: + lldb.SBValueList: The SBValueList containing the SBValue for each resolved variable. + Returns None by default. + """ + return None + + def get_register_info(self): + if self.register_info is None: + self.register_info = self.originating_thread.get_register_info() + return self.register_info + + @abstractmethod + def get_register_context(self): + """Get the scripted thread register context + + Returns: + str: A byte representing all register's value. + """ + pass class PassthroughScriptedProcess(ScriptedProcess): driving_target = None diff --git a/lldb/include/lldb/API/SBSymbolContext.h b/lldb/include/lldb/API/SBSymbolContext.h index 128b0b65b7860..19f29c629d094 100644 --- a/lldb/include/lldb/API/SBSymbolContext.h +++ b/lldb/include/lldb/API/SBSymbolContext.h @@ -66,6 +66,7 @@ class LLDB_API SBSymbolContext { friend class SBTarget; friend class SBSymbolContextList; + friend class lldb_private::ScriptInterpreter; friend class lldb_private::python::SWIGBridge; SBSymbolContext(const lldb_private::SymbolContext &sc_ptr); diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h new file mode 100644 index 0000000000000..8ef4b37d6ba12 --- /dev/null +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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_SCRIPTEDFRAMEINTERFACE_H +#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEINTERFACE_H + +#include "ScriptedInterface.h" +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/lldb-private.h" +#include +#include + +namespace lldb_private { +class ScriptedFrameInterface : virtual public ScriptedInterface { +public: + virtual llvm::Expected + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) = 0; + + virtual lldb::user_id_t GetID() { return LLDB_INVALID_FRAME_ID; } + + virtual lldb::addr_t GetPC() { return LLDB_INVALID_ADDRESS; } + + virtual std::optional GetSymbolContext() { + return std::nullopt; + } + + virtual std::optional GetFunctionName() { return std::nullopt; } + + virtual std::optional GetDisplayFunctionName() { + return std::nullopt; + } + + virtual bool IsInlined() { return false; } + + virtual bool IsArtificial() { return false; } + + virtual bool IsHidden() { return false; } + + virtual StructuredData::DictionarySP GetRegisterInfo() { return {}; } + + virtual std::optional GetRegisterContext() { + return std::nullopt; + } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEINTERFACE_H diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h index a7cfc690b67dc..bc58f344d36f8 100644 --- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h @@ -44,6 +44,16 @@ class ScriptedThreadInterface : virtual public ScriptedInterface { } virtual StructuredData::ArraySP GetExtendedInfo() { return {}; } + + virtual std::optional GetScriptedFramePluginName() { + return std::nullopt; + } + +protected: + friend class ScriptedFrame; + virtual lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() { + return {}; + } }; } // namespace lldb_private diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 34deeb6c7a39b..5eb41390eca0c 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -26,6 +26,7 @@ #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h" #include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h" @@ -533,6 +534,10 @@ class ScriptInterpreter : public PluginInterface { return {}; } + virtual lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() { + return {}; + } + virtual lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() { return {}; diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index a325af126e621..a3b3e9da8e68b 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -398,7 +398,7 @@ class StackFrame : public ExecutionContextScope, /// /// \return /// true if this is an inlined frame. - bool IsInlined(); + virtual bool IsInlined(); /// Query whether this frame is synthetic. bool IsSynthetic() const; @@ -409,12 +409,12 @@ class StackFrame : public ExecutionContextScope, /// Query whether this frame is artificial (e.g a synthesized result of /// inferring missing tail call frames from a backtrace). Artificial frames /// may have limited support for inspecting variables. - bool IsArtificial() const; + virtual bool IsArtificial() const; /// Query whether this frame should be hidden from backtraces. Frame /// recognizers can customize this behavior and hide distracting /// system implementation details this way. - bool IsHidden(); + virtual bool IsHidden(); /// Query whether this frame is a Swift Thunk. LLDB_DEPRECATED("Use IsHidden() instead.") @@ -429,13 +429,13 @@ class StackFrame : public ExecutionContextScope, /// /// /// \return /// A C-String containing the function demangled name. Can be null. - const char *GetFunctionName(); + virtual const char *GetFunctionName(); /// Get the frame's demangled display name. /// /// /// \return /// A C-String containing the function demangled display name. Can be null. - const char *GetDisplayFunctionName(); + virtual const char *GetDisplayFunctionName(); /// Query this frame to find what frame it is in this Thread's /// StackFrameList. @@ -547,8 +547,7 @@ class StackFrame : public ExecutionContextScope, bool HasCachedData() const; -private: - /// For StackFrame only. + /// For StackFrame and derived classes only. /// \{ lldb::ThreadWP m_thread_wp; uint32_t m_frame_index; @@ -585,6 +584,17 @@ class StackFrame : public ExecutionContextScope, StreamString m_disassembly; std::recursive_mutex m_mutex; +private: + /// Private methods, called from GetValueForVariableExpressionPath. + /// See that method for documentation of parameters and return value. + lldb::ValueObjectSP LegacyGetValueForVariableExpressionPath( + llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, + uint32_t options, lldb::VariableSP &var_sp, Status &error); + + lldb::ValueObjectSP DILGetValueForVariableExpressionPath( + llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, + uint32_t options, lldb::VariableSP &var_sp, Status &error); + StackFrame(const StackFrame &) = delete; const StackFrame &operator=(const StackFrame &) = delete; }; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 319bdef3b8dbd..f4523bdbc9dcb 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -187,6 +187,7 @@ class SaveCoreOptions; class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; +class ScriptedFrameInterface; class ScriptedMetadata; class ScriptedBreakpointInterface; class ScriptedPlatformInterface; @@ -407,6 +408,8 @@ typedef std::shared_ptr typedef std::shared_ptr ScriptSummaryFormatSP; typedef std::shared_ptr ScriptInterpreterSP; +typedef std::shared_ptr + ScriptedFrameInterfaceSP; typedef std::shared_ptr ScriptedMetadataSP; typedef std::unique_ptr ScriptedPlatformInterfaceUP; diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index 9c321125d3c40..d9dbd4d0c896b 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -1691,7 +1691,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, StackFrame *frame = exe_ctx->GetFramePtr(); if (frame) { const Address &pc_addr = frame->GetFrameCodeAddress(); - if (pc_addr.IsValid()) { + if (pc_addr.IsValid() || frame->IsSynthetic()) { if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false)) return true; } diff --git a/lldb/source/Plugins/Process/scripted/CMakeLists.txt b/lldb/source/Plugins/Process/scripted/CMakeLists.txt index 600ef31d032eb..4931e028b3099 100644 --- a/lldb/source/Plugins/Process/scripted/CMakeLists.txt +++ b/lldb/source/Plugins/Process/scripted/CMakeLists.txt @@ -1,6 +1,7 @@ add_lldb_library(lldbPluginScriptedProcess PLUGIN ScriptedProcess.cpp ScriptedThread.cpp + ScriptedFrame.cpp LINK_LIBS lldbCore diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp new file mode 100644 index 0000000000000..6519df9185df0 --- /dev/null +++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp @@ -0,0 +1,191 @@ +//===----------------------------------------------------------------------===// +// +// 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 "ScriptedFrame.h" + +#include "lldb/Utility/DataBufferHeap.h" + +using namespace lldb; +using namespace lldb_private; + +void ScriptedFrame::CheckInterpreterAndScriptObject() const { + lldbassert(m_script_object_sp && "Invalid Script Object."); + lldbassert(GetInterface() && "Invalid Scripted Frame Interface."); +} + +llvm::Expected> +ScriptedFrame::Create(ScriptedThread &thread, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_object) { + if (!thread.IsValid()) + return llvm::createStringError("Invalid scripted thread."); + + thread.CheckInterpreterAndScriptObject(); + + auto scripted_frame_interface = + thread.GetInterface()->CreateScriptedFrameInterface(); + if (!scripted_frame_interface) + return llvm::createStringError("failed to create scripted frame interface"); + + llvm::StringRef frame_class_name; + if (!script_object) { + std::optional class_name = + thread.GetInterface()->GetScriptedFramePluginName(); + if (!class_name || class_name->empty()) + return llvm::createStringError( + "failed to get scripted thread class name"); + frame_class_name = *class_name; + } + + ExecutionContext exe_ctx(thread); + auto obj_or_err = scripted_frame_interface->CreatePluginObject( + frame_class_name, exe_ctx, args_sp, script_object); + + if (!obj_or_err) + return llvm::createStringError( + "failed to create script object: %s", + llvm::toString(obj_or_err.takeError()).c_str()); + + StructuredData::GenericSP owned_script_object_sp = *obj_or_err; + + if (!owned_script_object_sp->IsValid()) + return llvm::createStringError("created script object is invalid"); + + lldb::user_id_t frame_id = scripted_frame_interface->GetID(); + + lldb::addr_t pc = scripted_frame_interface->GetPC(); + SymbolContext sc; + Address symbol_addr; + if (pc != LLDB_INVALID_ADDRESS) { + symbol_addr.SetLoadAddress(pc, &thread.GetProcess()->GetTarget()); + symbol_addr.CalculateSymbolContext(&sc); + } + + std::optional maybe_sym_ctx = + scripted_frame_interface->GetSymbolContext(); + if (maybe_sym_ctx) { + sc = *maybe_sym_ctx; + } + + StructuredData::DictionarySP reg_info = + scripted_frame_interface->GetRegisterInfo(); + + if (!reg_info) + return llvm::createStringError( + "failed to get scripted thread registers info"); + + std::shared_ptr register_info_sp = + DynamicRegisterInfo::Create( + *reg_info, thread.GetProcess()->GetTarget().GetArchitecture()); + + lldb::RegisterContextSP reg_ctx_sp; + + std::optional reg_data = + scripted_frame_interface->GetRegisterContext(); + if (reg_data) { + DataBufferSP data_sp( + std::make_shared(reg_data->c_str(), reg_data->size())); + + if (!data_sp->GetByteSize()) + return llvm::createStringError("failed to copy raw registers data"); + + std::shared_ptr reg_ctx_memory = + std::make_shared( + thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS); + if (!reg_ctx_memory) + return llvm::createStringError("failed to create a register context."); + + reg_ctx_memory->SetAllRegisterData(data_sp); + reg_ctx_sp = reg_ctx_memory; + } + + return std::make_shared( + thread, scripted_frame_interface, frame_id, pc, sc, reg_ctx_sp, + register_info_sp, owned_script_object_sp); +} + +ScriptedFrame::ScriptedFrame(ScriptedThread &thread, + ScriptedFrameInterfaceSP interface_sp, + lldb::user_id_t id, lldb::addr_t pc, + SymbolContext &sym_ctx, + lldb::RegisterContextSP reg_ctx_sp, + std::shared_ptr reg_info_sp, + StructuredData::GenericSP script_object_sp) + : StackFrame(thread.shared_from_this(), /*frame_idx=*/id, + /*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp, + /*cfa=*/0, /*pc=*/pc, + /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx), + m_scripted_frame_interface_sp(interface_sp), + m_script_object_sp(script_object_sp), m_register_info_sp(reg_info_sp) {} + +ScriptedFrame::~ScriptedFrame() {} + +const char *ScriptedFrame::GetFunctionName() { + CheckInterpreterAndScriptObject(); + std::optional function_name = GetInterface()->GetFunctionName(); + if (!function_name) + return nullptr; + return ConstString(function_name->c_str()).AsCString(); +} + +const char *ScriptedFrame::GetDisplayFunctionName() { + CheckInterpreterAndScriptObject(); + std::optional function_name = + GetInterface()->GetDisplayFunctionName(); + if (!function_name) + return nullptr; + return ConstString(function_name->c_str()).AsCString(); +} + +bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); } + +bool ScriptedFrame::IsArtificial() const { + return GetInterface()->IsArtificial(); +} + +bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); } + +lldb::ScriptedFrameInterfaceSP ScriptedFrame::GetInterface() const { + return m_scripted_frame_interface_sp; +} + +std::shared_ptr ScriptedFrame::GetDynamicRegisterInfo() { + CheckInterpreterAndScriptObject(); + + if (!m_register_info_sp) { + StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo(); + + Status error; + if (!reg_info) + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr>( + LLVM_PRETTY_FUNCTION, "Failed to get scripted frame registers info.", + error, LLDBLog::Thread); + + ThreadSP thread_sp = m_thread_wp.lock(); + if (!thread_sp || !thread_sp->IsValid()) + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr>( + LLVM_PRETTY_FUNCTION, + "Failed to get scripted frame registers info: invalid thread.", error, + LLDBLog::Thread); + + ProcessSP process_sp = thread_sp->GetProcess(); + if (!process_sp || !process_sp->IsValid()) + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr>( + LLVM_PRETTY_FUNCTION, + "Failed to get scripted frame registers info: invalid process.", + error, LLDBLog::Thread); + + m_register_info_sp = DynamicRegisterInfo::Create( + *reg_info, process_sp->GetTarget().GetArchitecture()); + } + + return m_register_info_sp; +} diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.h b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h new file mode 100644 index 0000000000000..6e01e2fd7653e --- /dev/null +++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.h @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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_SCRIPTED_FRAME_H +#define LLDB_SOURCE_PLUGINS_SCRIPTED_FRAME_H + +#include "Plugins/Process/Utility/RegisterContextMemory.h" +#include "ScriptedThread.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/DynamicRegisterInfo.h" +#include "lldb/Target/StackFrame.h" +#include + +namespace lldb_private { +class ScriptedThread; +} + +namespace lldb_private { + +class ScriptedFrame : public lldb_private::StackFrame { + +public: + ScriptedFrame(ScriptedThread &thread, + lldb::ScriptedFrameInterfaceSP interface_sp, + lldb::user_id_t frame_idx, lldb::addr_t pc, + SymbolContext &sym_ctx, lldb::RegisterContextSP reg_ctx_sp, + std::shared_ptr reg_info_sp, + StructuredData::GenericSP script_object_sp = nullptr); + + ~ScriptedFrame() override; + + static llvm::Expected> + Create(ScriptedThread &thread, StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_object = nullptr); + + bool IsInlined() override; + bool IsArtificial() const override; + bool IsHidden() override; + const char *GetFunctionName() override; + const char *GetDisplayFunctionName() override; + +private: + void CheckInterpreterAndScriptObject() const; + lldb::ScriptedFrameInterfaceSP GetInterface() const; + + ScriptedFrame(const ScriptedFrame &) = delete; + const ScriptedFrame &operator=(const ScriptedFrame &) = delete; + + std::shared_ptr GetDynamicRegisterInfo(); + + lldb::ScriptedFrameInterfaceSP m_scripted_frame_interface_sp; + lldb_private::StructuredData::GenericSP m_script_object_sp; + std::shared_ptr m_register_info_sp; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_FRAME_H diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp index a2a8c5653d1d5..9c625d8cad31f 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ScriptedThread.h" +#include "ScriptedFrame.h" #include "Plugins/Process/Utility/RegisterContextThreadMemory.h" #include "Plugins/Process/Utility/StopInfoMachException.h" @@ -173,27 +174,31 @@ bool ScriptedThread::LoadArtificialStackFrames() { .str(), error, LLDBLog::Thread); - StackFrameListSP frames = GetStackFrameList(); - - for (size_t idx = 0; idx < arr_size; idx++) { + auto create_frame_from_dict = + [this, arr_sp](size_t idx) -> llvm::Expected { + Status error; std::optional maybe_dict = arr_sp->GetItemAtIndexAsDictionary(idx); - if (!maybe_dict) - return ScriptedInterface::ErrorWithMessage( + if (!maybe_dict) { + ScriptedInterface::ErrorWithMessage( LLVM_PRETTY_FUNCTION, llvm::Twine( "Couldn't get artificial stackframe dictionary at index (" + llvm::Twine(idx) + llvm::Twine(") from stackframe array.")) .str(), error, LLDBLog::Thread); + return error.ToError(); + } StructuredData::Dictionary *dict = *maybe_dict; lldb::addr_t pc; - if (!dict->GetValueForKeyAsInteger("pc", pc)) - return ScriptedInterface::ErrorWithMessage( + if (!dict->GetValueForKeyAsInteger("pc", pc)) { + ScriptedInterface::ErrorWithMessage( LLVM_PRETTY_FUNCTION, "Couldn't find value for key 'pc' in stackframe dictionary.", error, LLDBLog::Thread); + return error.ToError(); + } Address symbol_addr; symbol_addr.SetLoadAddress(pc, &this->GetProcess()->GetTarget()); @@ -205,10 +210,65 @@ bool ScriptedThread::LoadArtificialStackFrames() { SymbolContext sc; symbol_addr.CalculateSymbolContext(&sc); - StackFrameSP synth_frame_sp = std::make_shared( - this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc, - StackFrame::Kind::Synthetic, artificial, behaves_like_zeroth_frame, - &sc); + return std::make_shared(this->shared_from_this(), idx, idx, cfa, + cfa_is_valid, pc, + StackFrame::Kind::Synthetic, artificial, + behaves_like_zeroth_frame, &sc); + }; + + auto create_frame_from_script_object = + [this, arr_sp](size_t idx) -> llvm::Expected { + Status error; + StructuredData::ObjectSP object_sp = arr_sp->GetItemAtIndex(idx); + if (!object_sp || !object_sp->GetAsGeneric()) { + ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Couldn't get artificial stackframe object at index (" + + llvm::Twine(idx) + + llvm::Twine(") from stackframe array.")) + .str(), + error, LLDBLog::Thread); + return error.ToError(); + } + + auto frame_or_error = + ScriptedFrame::Create(*this, nullptr, object_sp->GetAsGeneric()); + + if (!frame_or_error) { + ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, toString(frame_or_error.takeError()), error); + return error.ToError(); + } + + StackFrameSP frame_sp = frame_or_error.get(); + lldbassert(frame_sp && "Couldn't initialize scripted frame."); + + return frame_sp; + }; + + StackFrameListSP frames = GetStackFrameList(); + + for (size_t idx = 0; idx < arr_size; idx++) { + StackFrameSP synth_frame_sp = nullptr; + + auto frame_from_dict_or_err = create_frame_from_dict(idx); + if (!frame_from_dict_or_err) { + auto frame_from_script_obj_or_err = create_frame_from_script_object(idx); + + if (!frame_from_script_obj_or_err) { + return ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Couldn't add artificial frame (" + llvm::Twine(idx) + + llvm::Twine(") to ScriptedThread StackFrameList.")) + .str(), + error, LLDBLog::Thread); + } else { + llvm::consumeError(frame_from_dict_or_err.takeError()); + synth_frame_sp = *frame_from_script_obj_or_err; + } + } else { + synth_frame_sp = *frame_from_dict_or_err; + } if (!frames->SetFrameAtIndex(static_cast(idx), synth_frame_sp)) return ScriptedInterface::ErrorWithMessage( diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.h b/lldb/source/Plugins/Process/scripted/ScriptedThread.h index cd224d60ceef8..ee5ace4059673 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedThread.h +++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.h @@ -15,11 +15,12 @@ #include "Plugins/Process/Utility/RegisterContextMemory.h" #include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Target//DynamicRegisterInfo.h" +#include "lldb/Target/DynamicRegisterInfo.h" #include "lldb/Target/Thread.h" namespace lldb_private { class ScriptedProcess; +class ScriptedFrame; } namespace lldb_private { @@ -61,6 +62,8 @@ class ScriptedThread : public lldb_private::Thread { StructuredData::ObjectSP FetchThreadExtendedInfo() override; private: + friend class ScriptedFrame; + void CheckInterpreterAndScriptObject() const; lldb::ScriptedThreadInterfaceSP GetInterface() const; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt index 29963a334ad94..4c31b5efedac6 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt @@ -22,6 +22,7 @@ endif() add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN OperatingSystemPythonInterface.cpp ScriptInterpreterPythonInterfaces.cpp + ScriptedFramePythonInterface.cpp ScriptedPlatformPythonInterface.cpp ScriptedProcessPythonInterface.cpp ScriptedPythonInterface.cpp diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h index 02dc06507caf2..3814f46615078 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h @@ -17,6 +17,7 @@ #include "OperatingSystemPythonInterface.h" #include "ScriptedBreakpointPythonInterface.h" +#include "ScriptedFramePythonInterface.h" #include "ScriptedPlatformPythonInterface.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedStopHookPythonInterface.h" diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp new file mode 100644 index 0000000000000..20ca7a2c01356 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp @@ -0,0 +1,157 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/Log.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 "ScriptedFramePythonInterface.h" +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedFramePythonInterface::ScriptedFramePythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedFrameInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected +ScriptedFramePythonInterface::CreatePluginObject( + const llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared(exe_ctx); + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); +} + +lldb::user_id_t ScriptedFramePythonInterface::GetID() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_id", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return LLDB_INVALID_FRAME_ID; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_FRAME_ID); +} + +lldb::addr_t ScriptedFramePythonInterface::GetPC() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_pc", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return LLDB_INVALID_ADDRESS; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS); +} + +std::optional ScriptedFramePythonInterface::GetSymbolContext() { + Status error; + auto sym_ctx = Dispatch("get_symbol_context", error); + + if (error.Fail()) { + return ErrorWithMessage(LLVM_PRETTY_FUNCTION, + error.AsCString(), error); + } + + return sym_ctx; +} + +std::optional ScriptedFramePythonInterface::GetFunctionName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_function_name", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetStringValue().str(); +} + +std::optional +ScriptedFramePythonInterface::GetDisplayFunctionName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_display_function_name", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetStringValue().str(); +} + +bool ScriptedFramePythonInterface::IsInlined() { + Status error; + StructuredData::ObjectSP obj = Dispatch("is_inlined", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return false; + + return obj->GetBooleanValue(); +} + +bool ScriptedFramePythonInterface::IsArtificial() { + Status error; + StructuredData::ObjectSP obj = Dispatch("is_artificial", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return false; + + return obj->GetBooleanValue(); +} + +bool ScriptedFramePythonInterface::IsHidden() { + Status error; + StructuredData::ObjectSP obj = Dispatch("is_hidden", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return false; + + return obj->GetBooleanValue(); +} + +StructuredData::DictionarySP ScriptedFramePythonInterface::GetRegisterInfo() { + Status error; + StructuredData::DictionarySP dict = + Dispatch("get_register_info", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +std::optional ScriptedFramePythonInterface::GetRegisterContext() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_register_context", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetAsString()->GetValue().str(); +} + +#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h new file mode 100644 index 0000000000000..3aff237ae65d5 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDFRAMEPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDFRAMEPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h" +#include + +namespace lldb_private { +class ScriptedFramePythonInterface : public ScriptedFrameInterface, + public ScriptedPythonInterface { +public: + ScriptedFramePythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector + GetAbstractMethodRequirements() const override { + return llvm::SmallVector({{"get_id"}}); + } + + lldb::user_id_t GetID() override; + + lldb::addr_t GetPC() override; + + std::optional GetSymbolContext() override; + + std::optional GetFunctionName() override; + + std::optional GetDisplayFunctionName() override; + + bool IsInlined() override; + + bool IsArtificial() override; + + bool IsHidden() override; + + StructuredData::DictionarySP GetRegisterInfo() override; + + std::optional GetRegisterContext() override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDFRAMEPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp index b49d1d82fe535..8083ccae04026 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -167,7 +167,8 @@ ScriptedPythonInterface::ExtractValueFromPythonObject< if (!sb_mem_reg_info) { error = Status::FromErrorStringWithFormat( - "Couldn't cast lldb::SBMemoryRegionInfo to lldb::MemoryRegionInfoSP."); + "Couldn't cast lldb::SBMemoryRegionInfo to " + "lldb_private::MemoryRegionInfo."); return {}; } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp index 8af89d761764b..fd4d231a747fe 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp @@ -144,4 +144,21 @@ StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() { return arr; } +std::optional +ScriptedThreadPythonInterface::GetScriptedFramePluginName() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_scripted_frame_plugin", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetStringValue().str(); +} + +lldb::ScriptedFrameInterfaceSP +ScriptedThreadPythonInterface::CreateScriptedFrameInterface() { + return m_interpreter.CreateScriptedFrameInterface(); +} + #endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h index 1fb23b39c7076..043557a827461 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h @@ -51,6 +51,11 @@ class ScriptedThreadPythonInterface : public ScriptedThreadInterface, std::optional GetRegisterContext() override; StructuredData::ArraySP GetExtendedInfo() override; + + std::optional GetScriptedFramePluginName() override; + +protected: + lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 402c809201dde..6491a1ca87969 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1580,6 +1580,11 @@ ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() { return std::make_shared(*this); } +ScriptedFrameInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedFrameInterface() { + return std::make_shared(*this); +} + ScriptedThreadPlanInterfaceSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() { return std::make_shared(*this); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 9845c88636488..5939f8d88aa9d 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -99,6 +99,8 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; + lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override; + lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() override; diff --git a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py index 2721d961bcb9d..835267221ddb4 100644 --- a/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py @@ -5,6 +5,7 @@ import lldb from lldb.plugins.scripted_process import ScriptedProcess from lldb.plugins.scripted_process import ScriptedThread +from lldb.plugins.scripted_process import ScriptedFrame class DummyStopHook: @@ -22,7 +23,7 @@ class DummyScriptedProcess(ScriptedProcess): def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData): super().__init__(exe_ctx, args) - self.threads[0] = DummyScriptedThread(self, None) + self.threads[0] = DummyScriptedThread(self, args) self.memory = {} addr = 0x500000000 debugger = self.target.GetDebugger() @@ -69,6 +70,9 @@ class DummyScriptedThread(ScriptedThread): def __init__(self, process, args): super().__init__(process, args) self.frames.append({"pc": 0x0100001B00}) + self.frames.append(DummyScriptedFrame(self, args, len(self.frames), "baz123")) + self.frames.append(DummyScriptedFrame(self, args, len(self.frames), "bar")) + self.frames.append(DummyScriptedFrame(self, args, len(self.frames), "foo")) def get_thread_id(self) -> int: return 0x19 @@ -109,6 +113,65 @@ def get_register_context(self) -> str: ) +class DummyScriptedFrame(ScriptedFrame): + def __init__(self, thread, args, id, name, sym_ctx=None): + super().__init__(thread, args) + self.id = id + self.name = name + self.sym_ctx = sym_ctx + + def get_id(self): + return self.id + + def get_function_name(self): + return self.name + + def get_register_context(self) -> str: + return struct.pack( + "21Q", + 0x10001, + 0x10002, + 0x10003, + 0x10004, + 0x10005, + 0x10006, + 0x10007, + 0x10008, + 0x10009, + 0x100010, + 0x100011, + 0x100012, + 0x100013, + 0x100014, + 0x100015, + 0x100016, + 0x100017, + 0x100018, + 0x100019, + 0x100020, + 0x100021, + ) + + def get_symbol_context(self): + def get_symbol_context_for_function(func_name): + module = self.target.FindModule(self.target.GetExecutable()) + if not module.IsValid(): + return None + + sym_ctx_list = module.FindFunctions(func_name) + if not sym_ctx_list.IsValid() or sym_ctx_list.GetSize() == 0: + return None + + return sym_ctx_list.GetContextAtIndex(0) + + return ( + self.sym_ctx if self.sym_ctx else get_symbol_context_for_function(self.name) + ) + + def get_scripted_frame_plugin(self): + return DummyScriptedFrame.__module__ + "." + DummyScriptedFrame.__name__ + + def __lldb_init_module(debugger, dict): # This is used when loading the script in an interactive debug session to # automatically, register the stop-hook and launch the scripted process. From e83d3c6d4134b8c7a4c333ebf3f9d9340f83559c Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Thu, 4 Sep 2025 23:07:12 -0700 Subject: [PATCH 15/15] [lldb] Regenerate python static bindings Signed-off-by: Med Ismail Bennani --- .../python/static-binding/LLDBWrapPython.cpp | 431 +++++++----------- lldb/bindings/python/static-binding/lldb.py | 4 + 2 files changed, 169 insertions(+), 266 deletions(-) diff --git a/lldb/bindings/python/static-binding/LLDBWrapPython.cpp b/lldb/bindings/python/static-binding/LLDBWrapPython.cpp index 54e8b274bab63..066aabb7ea772 100644 --- a/lldb/bindings/python/static-binding/LLDBWrapPython.cpp +++ b/lldb/bindings/python/static-binding/LLDBWrapPython.cpp @@ -3368,102 +3368,105 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { #define SWIGTYPE_p_std__shared_ptrT_lldb_private__RegularExpression_t swig_types[160] #define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptInterpreter_t swig_types[161] #define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t swig_types[162] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedMetadata_t swig_types[163] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t swig_types[164] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t swig_types[165] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t swig_types[166] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SearchFilter_t swig_types[167] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SectionLoadList_t swig_types[168] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Section_t swig_types[169] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StackFrameList_t swig_types[170] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StackFrameRecognizer_t swig_types[171] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StackFrame_t swig_types[172] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StopInfo_t swig_types[173] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StreamFile_t swig_types[174] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Stream_t swig_types[175] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StringSummaryFormat_t swig_types[176] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StructuredDataPlugin_t swig_types[177] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SupportFile_t swig_types[178] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SymbolContextSpecifier_t swig_types[179] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SymbolFileType_t swig_types[180] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SyntheticChildrenFrontEnd_t swig_types[181] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SyntheticChildren_t swig_types[182] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Target_t swig_types[183] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadCollection_t swig_types[184] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadPlanTracer_t swig_types[185] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadPlan_t swig_types[186] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadPostMortemTrace_t swig_types[187] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Thread_t swig_types[188] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TraceCursor_t swig_types[189] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Trace_t swig_types[190] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeCategoryImpl_t swig_types[191] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeEnumMemberImpl_t swig_types[192] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeFilterImpl_t swig_types[193] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeFormatImpl_t swig_types[194] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeImpl_t swig_types[195] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeMemberFunctionImpl_t swig_types[196] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeNameSpecifierImpl_t swig_types[197] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSummaryImpl_t swig_types[198] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSummaryOptions_t swig_types[199] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSystemClang_t swig_types[200] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSystem_t swig_types[201] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Type_t swig_types[202] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UnixSignals_t swig_types[203] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UnwindAssembly_t swig_types[204] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UnwindPlan_t swig_types[205] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UserExpression_t swig_types[206] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ValueObjectList_t swig_types[207] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ValueObject_t swig_types[208] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Value_t swig_types[209] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__VariableList_t swig_types[210] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Variable_t swig_types[211] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__WatchpointResource_t swig_types[212] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Watchpoint_t swig_types[213] -#define SWIGTYPE_p_std__shared_ptrT_lldb_private__WritableDataBuffer_t swig_types[214] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__AddressRange_t swig_types[215] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__DynamicCheckerFunctions_t swig_types[216] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__DynamicLoader_t swig_types[217] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__File_t swig_types[218] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__JITLoaderList_t swig_types[219] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__MemoryRegionInfo_t swig_types[220] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__OperatingSystem_t swig_types[221] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__ProtocolServer_t swig_types[222] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__ScriptedPlatformInterface_t swig_types[223] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__ScriptedProcessInterface_t swig_types[224] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SectionList_t swig_types[225] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SourceManager_t swig_types[226] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__StackFrameRecognizerManager_t swig_types[227] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__Stream_t swig_types[228] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__StructuredDataImpl_t swig_types[229] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SymbolVendor_t swig_types[230] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SystemRuntime_t swig_types[231] -#define SWIGTYPE_p_std__unique_ptrT_lldb_private__TraceExporter_t swig_types[232] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__BreakpointLocation_t swig_types[233] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Breakpoint_t swig_types[234] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__BroadcasterManager_t swig_types[235] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Debugger_t swig_types[236] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Listener_t swig_types[237] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Module_t swig_types[238] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__ObjectFileJITDelegate_t swig_types[239] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__OptionValue_t swig_types[240] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Process_t swig_types[241] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Queue_t swig_types[242] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Section_t swig_types[243] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__StackFrame_t swig_types[244] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__StructuredDataPlugin_t swig_types[245] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Target_t swig_types[246] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__ThreadPlan_t swig_types[247] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Thread_t swig_types[248] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__TypeSystem_t swig_types[249] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Type_t swig_types[250] -#define SWIGTYPE_p_std__weak_ptrT_lldb_private__UnixSignals_t swig_types[251] -#define SWIGTYPE_p_unsigned_char swig_types[252] -#define SWIGTYPE_p_unsigned_int swig_types[253] -#define SWIGTYPE_p_unsigned_long_long swig_types[254] -#define SWIGTYPE_p_unsigned_short swig_types[255] -#define SWIGTYPE_p_void swig_types[256] -static swig_type_info *swig_types[258]; -static swig_module_info swig_module = {swig_types, 257, 0, 0, 0, 0}; +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t swig_types[163] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t swig_types[164] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedMetadata_t swig_types[165] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t swig_types[166] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t swig_types[167] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t swig_types[168] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t swig_types[169] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SearchFilter_t swig_types[170] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SectionLoadList_t swig_types[171] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Section_t swig_types[172] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StackFrameList_t swig_types[173] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StackFrameRecognizer_t swig_types[174] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StackFrame_t swig_types[175] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StopInfo_t swig_types[176] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StreamFile_t swig_types[177] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Stream_t swig_types[178] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StringSummaryFormat_t swig_types[179] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__StructuredDataPlugin_t swig_types[180] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SupportFile_t swig_types[181] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SymbolContextSpecifier_t swig_types[182] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SymbolFileType_t swig_types[183] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SyntheticChildrenFrontEnd_t swig_types[184] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__SyntheticChildren_t swig_types[185] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Target_t swig_types[186] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadCollection_t swig_types[187] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadPlanTracer_t swig_types[188] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadPlan_t swig_types[189] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ThreadPostMortemTrace_t swig_types[190] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Thread_t swig_types[191] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TraceCursor_t swig_types[192] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Trace_t swig_types[193] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeCategoryImpl_t swig_types[194] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeEnumMemberImpl_t swig_types[195] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeFilterImpl_t swig_types[196] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeFormatImpl_t swig_types[197] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeImpl_t swig_types[198] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeMemberFunctionImpl_t swig_types[199] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeNameSpecifierImpl_t swig_types[200] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSummaryImpl_t swig_types[201] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSummaryOptions_t swig_types[202] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSystemClang_t swig_types[203] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__TypeSystem_t swig_types[204] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Type_t swig_types[205] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UnixSignals_t swig_types[206] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UnwindAssembly_t swig_types[207] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UnwindPlan_t swig_types[208] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__UserExpression_t swig_types[209] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ValueObjectList_t swig_types[210] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__ValueObject_t swig_types[211] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Value_t swig_types[212] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__VariableList_t swig_types[213] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Variable_t swig_types[214] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__WatchpointResource_t swig_types[215] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__Watchpoint_t swig_types[216] +#define SWIGTYPE_p_std__shared_ptrT_lldb_private__WritableDataBuffer_t swig_types[217] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__AddressRange_t swig_types[218] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__DynamicCheckerFunctions_t swig_types[219] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__DynamicLoader_t swig_types[220] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__File_t swig_types[221] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__JITLoaderList_t swig_types[222] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__MemoryRegionInfo_t swig_types[223] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__OperatingSystem_t swig_types[224] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__ProtocolServer_t swig_types[225] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__ScriptedPlatformInterface_t swig_types[226] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__ScriptedProcessInterface_t swig_types[227] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SectionList_t swig_types[228] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SourceManager_t swig_types[229] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__StackFrameRecognizerManager_t swig_types[230] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__Stream_t swig_types[231] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__StructuredDataImpl_t swig_types[232] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SymbolVendor_t swig_types[233] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__SystemRuntime_t swig_types[234] +#define SWIGTYPE_p_std__unique_ptrT_lldb_private__TraceExporter_t swig_types[235] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__BreakpointLocation_t swig_types[236] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Breakpoint_t swig_types[237] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__BroadcasterManager_t swig_types[238] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Debugger_t swig_types[239] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Listener_t swig_types[240] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Module_t swig_types[241] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__ObjectFileJITDelegate_t swig_types[242] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__OptionValue_t swig_types[243] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Process_t swig_types[244] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Queue_t swig_types[245] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Section_t swig_types[246] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__StackFrame_t swig_types[247] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__StructuredDataPlugin_t swig_types[248] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Target_t swig_types[249] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__ThreadPlan_t swig_types[250] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Thread_t swig_types[251] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__TypeSystem_t swig_types[252] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__Type_t swig_types[253] +#define SWIGTYPE_p_std__weak_ptrT_lldb_private__UnixSignals_t swig_types[254] +#define SWIGTYPE_p_unsigned_char swig_types[255] +#define SWIGTYPE_p_unsigned_int swig_types[256] +#define SWIGTYPE_p_unsigned_long_long swig_types[257] +#define SWIGTYPE_p_unsigned_short swig_types[258] +#define SWIGTYPE_p_void swig_types[259] +static swig_type_info *swig_types[261]; +static swig_module_info swig_module = {swig_types, 260, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -5043,176 +5046,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject return pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger_sp)), dict); } -PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver( - const char *python_class_name, const char *session_dictionary_name, - const StructuredDataImpl &args_impl, - const lldb::BreakpointSP &breakpoint_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( - session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary( - python_class_name, dict); - - if (!pfunc.IsAllocated()) - return PythonObject(); - - PythonObject result = - pfunc(SWIGBridge::ToSWIGWrapper(breakpoint_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict); - // FIXME: At this point we should check that the class we found supports all - // the methods that we need. - - if (result.IsAllocated()) { - // Check that __callback__ is defined: - auto callback_func = result.ResolveName("__callback__"); - if (callback_func.IsAllocated()) - return result; - } - return PythonObject(); -} - -unsigned int lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver( - void *implementor, const char *method_name, - lldb_private::SymbolContext *sym_ctx) { - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName(method_name); - - if (!pfunc.IsAllocated()) - return 0; - - PythonObject result = sym_ctx ? pfunc(SWIGBridge::ToSWIGWrapper(*sym_ctx)) : pfunc(); - - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return 0; - } - - // The callback will return a bool, but we're need to also return ints - // so we're squirrelling the bool through as an int... And if you return - // nothing, we'll continue. - if (strcmp(method_name, "__callback__") == 0) { - if (result.get() == Py_False) - return 0; - else - return 1; - } - - long long ret_val = unwrapOrSetPythonException(As(result)); - - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return 0; - } - - return ret_val; -} - -PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedStopHook( - lldb::TargetSP target_sp, const char *python_class_name, - const char *session_dictionary_name, const StructuredDataImpl &args_impl, - Status &error) { - if (python_class_name == NULL || python_class_name[0] == '\0') { - error = Status::FromErrorString("Empty class name."); - return PythonObject(); - } - if (!session_dictionary_name) { - error = Status::FromErrorString("No session dictionary"); - return PythonObject(); - } - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = PythonModule::MainModule().ResolveName( - session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary( - python_class_name, dict); - - if (!pfunc.IsAllocated()) { - error = Status::FromErrorStringWithFormat("Could not find class: %s.", - python_class_name); - return PythonObject(); - } - - PythonObject result = - pfunc(SWIGBridge::ToSWIGWrapper(target_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict); - - if (result.IsAllocated()) { - // Check that the handle_stop callback is defined: - auto callback_func = result.ResolveName("handle_stop"); - if (callback_func.IsAllocated()) { - if (auto args_info = callback_func.GetArgInfo()) { - size_t num_args = (*args_info).max_positional_args; - if (num_args != 2) { - error = Status::FromErrorStringWithFormat( - "Wrong number of args for " - "handle_stop callback, should be 2 (excluding self), got: %zu", - num_args); - return PythonObject(); - } else - return result; - } else { - error = Status::FromErrorString( - "Couldn't get num arguments for handle_stop " - "callback."); - return PythonObject(); - } - return result; - } else { - error = Status::FromErrorStringWithFormat( - "Class \"%s\" is missing the required " - "handle_stop callback.", - python_class_name); - } - } - return PythonObject(); -} - -bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop( - void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp, - lldb::StreamSP stream) { - // handle_stop will return a bool with the meaning "should_stop"... - // If you return nothing we'll assume we are going to stop. - // Also any errors should return true, since we should stop on error. - - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName("handle_stop"); - - if (!pfunc.IsAllocated()) - return true; - - std::shared_ptr sb_stream = std::make_shared(); - PythonObject sb_stream_arg = SWIGBridge::ToSWIGWrapper(sb_stream); - PythonObject result = - pfunc(SWIGBridge::ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg); - - if (PyErr_Occurred()) { - stream->PutCString("Python error occurred handling stop-hook."); - PyErr_Print(); - PyErr_Clear(); - return true; - } - - // Now add the result to the output stream. SBStream only - // makes an internally help StreamString which I can't interpose, so I - // have to copy it over here. - stream->PutCString(sb_stream->GetData()); - sb_stream_arg.release(); - - if (result.get() == Py_False) - return false; - else - return true; -} - // wrapper that calls an optional instance member of an object taking no // arguments static PyObject *LLDBSwigPython_CallOptionalMember( @@ -5466,6 +5299,18 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * dat return sb_ptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject * data) { + lldb::SBSymbolContext *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBSymbolContext, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) { lldb::SBValue *sb_ptr = NULL; @@ -5491,6 +5336,19 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyOb return sb_ptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject * + data) { + lldb::SBExecutionContext *sb_ptr = NULL; + + int valid_cast = SWIG_ConvertPtr(data, (void **)&sb_ptr, + SWIGTYPE_p_lldb__SBExecutionContext, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommand( const char *python_function_name, const char *session_dictionary_name, lldb::DebuggerSP debugger, const char *args, @@ -37869,6 +37727,34 @@ SWIGINTERN PyObject *_wrap_SBFrame_IsArtificial(PyObject *self, PyObject *args) } +SWIGINTERN PyObject *_wrap_SBFrame_IsSynthetic(PyObject *self, PyObject *args) { + PyObject *resultobj = 0; + lldb::SBFrame *arg1 = (lldb::SBFrame *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + bool result; + + (void)self; + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_lldb__SBFrame, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SBFrame_IsSynthetic" "', argument " "1"" of type '" "lldb::SBFrame const *""'"); + } + arg1 = reinterpret_cast< lldb::SBFrame * >(argp1); + { + SWIG_PYTHON_THREAD_BEGIN_ALLOW; + result = (bool)((lldb::SBFrame const *)arg1)->IsSynthetic(); + SWIG_PYTHON_THREAD_END_ALLOW; + } + resultobj = SWIG_From_bool(static_cast< bool >(result)); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_SBFrame_IsHidden(PyObject *self, PyObject *args) { PyObject *resultobj = 0; lldb::SBFrame *arg1 = (lldb::SBFrame *) 0 ; @@ -97847,6 +97733,7 @@ static PyMethodDef SwigMethods[] = { " capture a tail call). Local variables may not be available in an artificial\n" " frame.\n" ""}, + { "SBFrame_IsSynthetic", _wrap_SBFrame_IsSynthetic, METH_O, "SBFrame_IsSynthetic(SBFrame self) -> bool"}, { "SBFrame_IsHidden", _wrap_SBFrame_IsHidden, METH_O, "SBFrame_IsHidden(SBFrame self) -> bool"}, { "SBFrame_EvaluateExpression", _wrap_SBFrame_EvaluateExpression, METH_VARARGS, "\n" "SBFrame_EvaluateExpression(SBFrame self, char const * expr) -> SBValue\n" @@ -101768,7 +101655,10 @@ static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__RegisterTypeBuild static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__RegularExpression_t = {"_p_std__shared_ptrT_lldb_private__RegularExpression_t", "lldb::RegularExpressionSP *|std::shared_ptr< lldb_private::RegularExpression > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptInterpreter_t = {"_p_std__shared_ptrT_lldb_private__ScriptInterpreter_t", "lldb::ScriptInterpreterSP *|std::shared_ptr< lldb_private::ScriptInterpreter > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t = {"_p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t", "lldb::ScriptSummaryFormatSP *|std::shared_ptr< lldb_private::ScriptSummaryFormat > *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t = {"_p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t", "lldb::ScriptedBreakpointInterfaceSP *|std::shared_ptr< lldb_private::ScriptedBreakpointInterface > *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t = {"_p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t", "lldb::ScriptedFrameInterfaceSP *|std::shared_ptr< lldb_private::ScriptedFrameInterface > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedMetadata_t = {"_p_std__shared_ptrT_lldb_private__ScriptedMetadata_t", "lldb::ScriptedMetadataSP *|std::shared_ptr< lldb_private::ScriptedMetadata > *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t = {"_p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t", "lldb::ScriptedStopHookInterfaceSP *|std::shared_ptr< lldb_private::ScriptedStopHookInterface > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t = {"_p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t", "lldb::ScriptedSyntheticChildrenSP *|std::shared_ptr< lldb_private::ScriptedSyntheticChildren > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t = {"_p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t", "lldb::ScriptedThreadInterfaceSP *|std::shared_ptr< lldb_private::ScriptedThreadInterface > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t = {"_p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t", "lldb::ScriptedThreadPlanInterfaceSP *|std::shared_ptr< lldb_private::ScriptedThreadPlanInterface > *", 0, 0, (void*)0, 0}; @@ -102027,7 +101917,10 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_std__shared_ptrT_lldb_private__RegularExpression_t, &_swigt__p_std__shared_ptrT_lldb_private__ScriptInterpreter_t, &_swigt__p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t, + &_swigt__p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t, + &_swigt__p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t, &_swigt__p_std__shared_ptrT_lldb_private__ScriptedMetadata_t, + &_swigt__p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t, &_swigt__p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t, &_swigt__p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t, &_swigt__p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t, @@ -102286,7 +102179,10 @@ static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__RegisterTypeBuild static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__RegularExpression_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__RegularExpression_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptInterpreter_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptInterpreter_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedMetadata_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedMetadata_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t[] = { {&_swigt__p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t, 0, 0, 0},{0, 0, 0, 0}}; @@ -102545,7 +102441,10 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_std__shared_ptrT_lldb_private__RegularExpression_t, _swigc__p_std__shared_ptrT_lldb_private__ScriptInterpreter_t, _swigc__p_std__shared_ptrT_lldb_private__ScriptSummaryFormat_t, + _swigc__p_std__shared_ptrT_lldb_private__ScriptedBreakpointInterface_t, + _swigc__p_std__shared_ptrT_lldb_private__ScriptedFrameInterface_t, _swigc__p_std__shared_ptrT_lldb_private__ScriptedMetadata_t, + _swigc__p_std__shared_ptrT_lldb_private__ScriptedStopHookInterface_t, _swigc__p_std__shared_ptrT_lldb_private__ScriptedSyntheticChildren_t, _swigc__p_std__shared_ptrT_lldb_private__ScriptedThreadInterface_t, _swigc__p_std__shared_ptrT_lldb_private__ScriptedThreadPlanInterface_t, diff --git a/lldb/bindings/python/static-binding/lldb.py b/lldb/bindings/python/static-binding/lldb.py index f1528a46cc284..aa23cab5f30c2 100644 --- a/lldb/bindings/python/static-binding/lldb.py +++ b/lldb/bindings/python/static-binding/lldb.py @@ -6499,6 +6499,10 @@ def IsArtificial(self, *args): """ return _lldb.SBFrame_IsArtificial(self, *args) + def IsSynthetic(self): + r"""IsSynthetic(SBFrame self) -> bool""" + return _lldb.SBFrame_IsSynthetic(self) + def IsHidden(self): r"""IsHidden(SBFrame self) -> bool""" return _lldb.SBFrame_IsHidden(self)