| //===----------------------------------------------------------------------===// | |
| // | |
| // 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/Breakpoint/Breakpoint.h" | |
| #include "lldb/Breakpoint/BreakpointLocation.h" | |
| #include "lldb/Breakpoint/BreakpointResolverScripted.h" | |
| #include "lldb/Core/PluginManager.h" | |
| #include "lldb/Symbol/SymbolContext.h" | |
| #include "lldb/Target/ExecutionContext.h" | |
| #include "lldb/Utility/Log.h" | |
| #include "lldb/lldb-enumerations.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<StructuredData::GenericSP> | |
| ScriptedBreakpointPythonInterface::CreatePluginObject( | |
| const ScriptedMetadata &scripted_metadata, lldb::BreakpointSP break_sp) { | |
| return ScriptedPythonInterface::CreatePluginObject( | |
| scripted_metadata, nullptr, break_sp, scripted_metadata.GetArgsSP()); | |
| } | |
| bool ScriptedBreakpointPythonInterface::OverridesResolver( | |
| Target &target, StructuredDataImpl &resolver_data) { | |
| Status error; | |
| TargetSP target_sp = target.shared_from_this(); | |
| StructuredData::ObjectSP obj = | |
| Dispatch("overrides_resolver", error, target_sp, resolver_data); | |
| if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, | |
| error)) { | |
| Log *log = GetLog(LLDBLog::Script); | |
| LLDB_LOG(log, "Error calling overrides_resolver method: {0}", error); | |
| return false; | |
| } | |
| return obj->GetBooleanValue(); | |
| } | |
| void ScriptedBreakpointPythonInterface::SetBreakpoint( | |
| lldb::BreakpointSP break_sp) { | |
| Status error; | |
| StructuredData::ObjectSP obj = Dispatch("set_breakpoint", error, break_sp); | |
| if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, | |
| error)) { | |
| Log *log = GetLog(LLDBLog::Script); | |
| LLDB_LOG(log, "Error calling set_breakpoint method: {0}", error); | |
| } | |
| } | |
| 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: {}", 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<std::string> 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(); | |
| } | |
| lldb::BreakpointLocationSP ScriptedBreakpointPythonInterface::WasHit( | |
| lldb::StackFrameSP frame_sp, lldb::BreakpointLocationSP bp_loc_sp) { | |
| Status py_error; | |
| lldb::BreakpointLocationSP loc_sp = Dispatch<lldb::BreakpointLocationSP>( | |
| "was_hit", py_error, frame_sp, bp_loc_sp); | |
| if (py_error.Fail()) | |
| return bp_loc_sp; | |
| return loc_sp; | |
| } | |
| std::optional<std::string> | |
| ScriptedBreakpointPythonInterface::GetLocationDescription( | |
| lldb::BreakpointLocationSP bp_loc_sp, lldb::DescriptionLevel level) { | |
| Status error; | |
| StructuredData::ObjectSP obj = | |
| Dispatch("get_location_description", error, bp_loc_sp, level); | |
| if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, | |
| error)) | |
| return {}; | |
| return obj->GetAsString()->GetValue().str(); | |
| } | |
| void ScriptedBreakpointPythonInterface::Initialize() { | |
| const std::vector<llvm::StringRef> ci_usages = { | |
| "breakpoint set -P classname [-k key -v value ...]"}; | |
| const std::vector<llvm::StringRef> api_usages = { | |
| "SBTarget.BreakpointCreateFromScript"}; | |
| PluginManager::RegisterPlugin( | |
| GetPluginNameStatic(), | |
| llvm::StringRef("Create a breakpoint that chooses locations based on " | |
| "user-created callbacks"), | |
| CreateInstance, eScriptedExtensionScriptedBreakpointResolver, | |
| eScriptLanguagePython, {ci_usages, api_usages}); | |
| } | |
| void ScriptedBreakpointPythonInterface::Terminate() { | |
| PluginManager::UnregisterPlugin(CreateInstance); | |
| } |