| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "../lldb-python.h" | |
| #include "lldb/Core/PluginManager.h" | |
| #include "lldb/Target/ScriptedThreadPlan.h" | |
| #include "lldb/Target/StackFrame.h" | |
| #include "lldb/Target/ThreadPlan.h" | |
| #include "lldb/Utility/StructuredData.h" | |
| #include "lldb/lldb-enumerations.h" | |
| #include "../SWIGPythonBridge.h" | |
| #include "../ScriptInterpreterPythonImpl.h" | |
| #include "ScriptedStackFrameRecognizerPythonInterface.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| using namespace lldb_private::python; | |
| ScriptedStackFrameRecognizerPythonInterface:: | |
| ScriptedStackFrameRecognizerPythonInterface( | |
| ScriptInterpreterPythonImpl &interpreter) | |
| : ScriptedStackFrameRecognizerInterface(), | |
| ScriptedPythonInterface(interpreter) {} | |
| llvm::Expected<StructuredData::GenericSP> | |
| ScriptedStackFrameRecognizerPythonInterface::CreatePluginObject( | |
| const ScriptedMetadata &scripted_metadata) { | |
| return ScriptedPythonInterface::CreatePluginObject(scripted_metadata, | |
| nullptr); | |
| } | |
| lldb::ValueObjectListSP | |
| ScriptedStackFrameRecognizerPythonInterface::GetRecognizedArguments( | |
| lldb::StackFrameSP frame_sp) { | |
| return LogAndDefault( | |
| Dispatch<lldb::ValueObjectListSP>("get_recognized_arguments", frame_sp), | |
| LLVM_PRETTY_FUNCTION); | |
| } | |
| bool ScriptedStackFrameRecognizerPythonInterface::ShouldHide( | |
| lldb::StackFrameSP frame_sp) { | |
| StructuredData::ObjectSP obj = | |
| LogAndDefault(Dispatch("should_hide", frame_sp), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return false; | |
| return obj->GetBooleanValue(); | |
| } | |
| lldb::StackFrameSP | |
| ScriptedStackFrameRecognizerPythonInterface::SelectMostRelevantFrame( | |
| lldb::StackFrameSP frame_sp) { | |
| return LogAndDefault( | |
| Dispatch<lldb::StackFrameSP>("select_most_relevant_frame", frame_sp), | |
| LLVM_PRETTY_FUNCTION); | |
| } | |
| lldb::ValueObjectSP ScriptedStackFrameRecognizerPythonInterface::GetException( | |
| lldb::StackFrameSP frame_sp) { | |
| return LogAndDefault(Dispatch<lldb::ValueObjectSP>("get_exception", frame_sp), | |
| LLVM_PRETTY_FUNCTION); | |
| } | |
| std::string ScriptedStackFrameRecognizerPythonInterface::GetStopDescription( | |
| lldb::StackFrameSP frame_sp) { | |
| StructuredData::ObjectSP obj = LogAndDefault( | |
| Dispatch("get_stop_description", frame_sp), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return ""; | |
| return obj->GetStringValue().str(); | |
| } | |
| lldb::ThreadPlanSP | |
| ScriptedStackFrameRecognizerPythonInterface::GetStepThroughPlan( | |
| lldb::ThreadSP thread_sp) { | |
| StructuredData::DictionarySP dict_sp = | |
| LogAndDefault(Dispatch<StructuredData::DictionarySP>( | |
| "get_step_through_plan", thread_sp), | |
| LLVM_PRETTY_FUNCTION); | |
| // The return value is an StructuredData::Dictionary with the class name and | |
| // the extra args for the call: | |
| if (!dict_sp || !dict_sp->IsValid()) | |
| return {}; | |
| StructuredData::ObjectSP obj = dict_sp->GetValueForKey("class_name"); | |
| if (!obj) | |
| return {}; | |
| llvm::StringRef class_string = obj->GetStringValue(); | |
| if (class_string.empty()) | |
| return {}; | |
| // Look for extra args, this is optional: | |
| StructuredData::Dictionary *extra_args_ptr = nullptr; | |
| StructuredData::DictionarySP extra_args_sp; | |
| if (dict_sp->GetValueForKeyAsDictionary("extra_args", extra_args_ptr)) | |
| extra_args_sp = std::static_pointer_cast<StructuredData::Dictionary>( | |
| extra_args_ptr->shared_from_this()); | |
| // Now make a new thread plan for stepping using the provided class name and | |
| // extra args. | |
| ScriptedMetadata plan_metadata(class_string, extra_args_sp); | |
| ThreadPlanSP step_through_plan_sp( | |
| new ScriptedThreadPlan(*thread_sp.get(), plan_metadata)); | |
| step_through_plan_sp->SetStopOthers(true); | |
| return step_through_plan_sp; | |
| } | |
| void ScriptedStackFrameRecognizerPythonInterface::Initialize() { | |
| const std::vector<llvm::StringRef> ci_usages = { | |
| "frame recognizer add -l <script-name> [-s <shlib> ...] " | |
| "[-n <symbol> ... | -x <symbol-regex>] [-f false] " | |
| "[--mangled-name-preference <mode>]"}; | |
| PluginManager::RegisterPlugin( | |
| GetPluginNameStatic(), | |
| "Recognize a stack frame and provide extra information about it " | |
| "(recognized arguments, exception object, stop description, " | |
| "hidden/most-relevant frame).", | |
| CreateInstance, eScriptedExtensionScriptedStackFrameRecognizer, | |
| eScriptLanguagePython, {ci_usages, {}}); | |
| } | |
| void ScriptedStackFrameRecognizerPythonInterface::Terminate() { | |
| PluginManager::UnregisterPlugin(CreateInstance); | |
| } |