| //===----------------------------------------------------------------------===// | |
| // | |
| // 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/Thread.h" | |
| #include "lldb/Utility/Log.h" | |
| #include "lldb/lldb-enumerations.h" | |
| #include "../SWIGPythonBridge.h" | |
| #include "../ScriptInterpreterPythonImpl.h" | |
| #include "ScriptedFrameProviderPythonInterface.h" | |
| #include <optional> | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| using namespace lldb_private::python; | |
| using Locker = ScriptInterpreterPythonImpl::Locker; | |
| ScriptedFrameProviderPythonInterface::ScriptedFrameProviderPythonInterface( | |
| ScriptInterpreterPythonImpl &interpreter) | |
| : ScriptedFrameProviderInterface(), ScriptedPythonInterface(interpreter) {} | |
| bool ScriptedFrameProviderPythonInterface::AppliesToThread( | |
| llvm::StringRef class_name, lldb::ThreadSP thread_sp) { | |
| // If there is any issue with this method, we will just assume it also applies | |
| // to this thread which is the default behavior. | |
| constexpr bool fail_value = true; | |
| StructuredData::ObjectSP obj = LogAndDefault( | |
| CallStaticMethod(class_name, "applies_to_thread", thread_sp), | |
| LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return fail_value; | |
| return obj->GetBooleanValue(fail_value); | |
| } | |
| llvm::Expected<StructuredData::GenericSP> | |
| ScriptedFrameProviderPythonInterface::CreatePluginObject( | |
| const ScriptedMetadata &scripted_metadata, | |
| lldb::StackFrameListSP input_frames) { | |
| if (!input_frames) | |
| return llvm::createStringError("invalid frame list"); | |
| return ScriptedPythonInterface::CreatePluginObject( | |
| scripted_metadata, nullptr, input_frames, scripted_metadata.GetArgsSP()); | |
| } | |
| std::string ScriptedFrameProviderPythonInterface::GetDescription( | |
| llvm::StringRef class_name) { | |
| StructuredData::ObjectSP obj = LogAndDefault( | |
| CallStaticMethod(class_name, "get_description"), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return {}; | |
| return obj->GetStringValue().str(); | |
| } | |
| std::optional<uint32_t> | |
| ScriptedFrameProviderPythonInterface::GetPriority(llvm::StringRef class_name) { | |
| StructuredData::ObjectSP obj = LogAndDefault( | |
| CallStaticMethod(class_name, "get_priority"), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return std::nullopt; | |
| // Try to extract as unsigned integer. Return nullopt if Python returned None | |
| // or if extraction fails. | |
| if (StructuredData::UnsignedInteger *int_obj = obj->GetAsUnsignedInteger()) | |
| return static_cast<uint32_t>(int_obj->GetValue()); | |
| return std::nullopt; | |
| } | |
| StructuredData::ObjectSP | |
| ScriptedFrameProviderPythonInterface::GetFrameAtIndex(uint32_t index) { | |
| StructuredData::ObjectSP obj = LogAndDefault( | |
| Dispatch("get_frame_at_index", index), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return {}; | |
| return obj; | |
| } | |
| bool ScriptedFrameProviderPythonInterface::CreateInstance( | |
| lldb::ScriptLanguage language, ScriptedInterfaceUsages usages) { | |
| if (language != eScriptLanguagePython) | |
| return false; | |
| return true; | |
| } | |
| void ScriptedFrameProviderPythonInterface::Initialize() { | |
| const std::vector<llvm::StringRef> ci_usages = { | |
| "target frame-provider register -C <script-name> [-k key -v value ...]", | |
| "target frame-provider list", | |
| "target frame-provider remove <provider-name>", | |
| "target frame-provider clear"}; | |
| const std::vector<llvm::StringRef> api_usages = { | |
| "SBTarget.RegisterScriptedFrameProvider", | |
| "SBTarget.RemoveScriptedFrameProvider", | |
| "SBTarget.ClearScriptedFrameProvider"}; | |
| PluginManager::RegisterPlugin( | |
| GetPluginNameStatic(), | |
| llvm::StringRef("Provide scripted stack frames for threads"), | |
| CreateInstance, eScriptedExtensionScriptedFrameProvider, | |
| eScriptLanguagePython, {ci_usages, api_usages}); | |
| } | |
| void ScriptedFrameProviderPythonInterface::Terminate() { | |
| PluginManager::UnregisterPlugin(CreateInstance); | |
| } |