| //===----------------------------------------------------------------------===// | |
| // | |
| // 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) { | |
| TargetSP target_sp = target.shared_from_this(); | |
| StructuredData::ObjectSP obj = | |
| LogAndDefault(Dispatch("overrides_resolver", target_sp, resolver_data), | |
| LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return false; | |
| return obj->GetBooleanValue(); | |
| } | |
| void ScriptedBreakpointPythonInterface::SetBreakpoint( | |
| lldb::BreakpointSP break_sp) { | |
| LogAndDefault(Dispatch("set_breakpoint", break_sp), LLVM_PRETTY_FUNCTION); | |
| } | |
| bool ScriptedBreakpointPythonInterface::ResolverCallback( | |
| SymbolContext sym_ctx) { | |
| StructuredData::ObjectSP obj = | |
| LogAndDefault(Dispatch("__callback__", sym_ctx), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return true; | |
| return obj->GetBooleanValue(); | |
| } | |
| lldb::SearchDepth ScriptedBreakpointPythonInterface::GetDepth() { | |
| StructuredData::ObjectSP obj = | |
| LogAndDefault(Dispatch("__get_depth__"), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| 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() { | |
| StructuredData::ObjectSP obj = | |
| LogAndDefault(Dispatch("get_short_help"), LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return {}; | |
| return obj->GetStringValue().str(); | |
| } | |
| lldb::BreakpointLocationSP ScriptedBreakpointPythonInterface::WasHit( | |
| lldb::StackFrameSP frame_sp, lldb::BreakpointLocationSP bp_loc_sp) { | |
| llvm::Expected<lldb::BreakpointLocationSP> loc_or_err = | |
| Dispatch<lldb::BreakpointLocationSP>("was_hit", frame_sp, bp_loc_sp); | |
| if (!loc_or_err) { | |
| LLDB_LOG_ERROR(GetLog(LLDBLog::Script), loc_or_err.takeError(), | |
| "Error calling was_hit method: {0}"); | |
| return bp_loc_sp; | |
| } | |
| return *loc_or_err; | |
| } | |
| std::optional<std::string> | |
| ScriptedBreakpointPythonInterface::GetLocationDescription( | |
| lldb::BreakpointLocationSP bp_loc_sp, lldb::DescriptionLevel level) { | |
| StructuredData::ObjectSP obj = | |
| LogAndDefault(Dispatch("get_location_description", bp_loc_sp, level), | |
| LLVM_PRETTY_FUNCTION); | |
| if (!obj) | |
| return {}; | |
| return obj->GetStringValue().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); | |
| } |