1 //===-- BreakpointResolverScripted.cpp ---------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Breakpoint/BreakpointResolverScripted.h" 10 11 12 #include "lldb/Breakpoint/BreakpointLocation.h" 13 #include "lldb/Core/Debugger.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/Section.h" 16 #include "lldb/Core/StructuredDataImpl.h" 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Interpreter/ScriptInterpreter.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Utility/Log.h" 22 #include "lldb/Utility/StreamString.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 // BreakpointResolverScripted: 28 BreakpointResolverScripted::BreakpointResolverScripted( 29 Breakpoint *bkpt, 30 const llvm::StringRef class_name, 31 lldb::SearchDepth depth, 32 StructuredDataImpl *args_data) 33 : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver), 34 m_class_name(class_name), m_depth(depth), m_args_ptr(args_data) { 35 CreateImplementationIfNeeded(); 36 } 37 38 void BreakpointResolverScripted::CreateImplementationIfNeeded() { 39 if (m_implementation_sp) 40 return; 41 42 if (m_class_name.empty()) 43 return; 44 45 if (m_breakpoint) { 46 TargetSP target_sp = m_breakpoint->GetTargetSP(); 47 ScriptInterpreter *script_interp = target_sp->GetDebugger() 48 .GetScriptInterpreter(); 49 if (!script_interp) 50 return; 51 lldb::BreakpointSP bkpt_sp(m_breakpoint->shared_from_this()); 52 m_implementation_sp = script_interp->CreateScriptedBreakpointResolver( 53 m_class_name.c_str(), m_args_ptr, bkpt_sp); 54 } 55 } 56 57 void BreakpointResolverScripted::NotifyBreakpointSet() { 58 CreateImplementationIfNeeded(); 59 } 60 61 BreakpointResolverScripted::~BreakpointResolverScripted() {} 62 63 BreakpointResolver * 64 BreakpointResolverScripted::CreateFromStructuredData( 65 Breakpoint *bkpt, const StructuredData::Dictionary &options_dict, 66 Status &error) { 67 llvm::StringRef class_name; 68 bool success; 69 70 success = options_dict.GetValueForKeyAsString( 71 GetKey(OptionNames::PythonClassName), class_name); 72 if (!success) { 73 error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); 74 return nullptr; 75 } 76 // The Python function will actually provide the search depth, this is a 77 // placeholder. 78 lldb::SearchDepth depth = lldb::eSearchDepthTarget; 79 80 StructuredDataImpl *args_data_impl = new StructuredDataImpl(); 81 StructuredData::Dictionary *args_dict = nullptr; 82 success = options_dict.GetValueForKeyAsDictionary( 83 GetKey(OptionNames::ScriptArgs), args_dict); 84 if (success) { 85 args_data_impl->SetObjectSP(args_dict->shared_from_this()); 86 } 87 return new BreakpointResolverScripted(bkpt, class_name, depth, 88 args_data_impl); 89 } 90 91 StructuredData::ObjectSP 92 BreakpointResolverScripted::SerializeToStructuredData() { 93 StructuredData::DictionarySP options_dict_sp( 94 new StructuredData::Dictionary()); 95 96 options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName), 97 m_class_name); 98 if (m_args_ptr->IsValid()) 99 options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs), 100 m_args_ptr->GetObjectSP()); 101 102 return WrapOptionsDict(options_dict_sp); 103 } 104 105 ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { 106 return m_breakpoint->GetTarget().GetDebugger().GetScriptInterpreter(); 107 } 108 109 Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( 110 SearchFilter &filter, SymbolContext &context, Address *addr) { 111 assert(m_breakpoint != nullptr); 112 bool should_continue = true; 113 if (!m_implementation_sp) 114 return Searcher::eCallbackReturnStop; 115 116 ScriptInterpreter *interp = GetScriptInterpreter(); 117 should_continue = interp->ScriptedBreakpointResolverSearchCallback( 118 m_implementation_sp, 119 &context); 120 if (should_continue) 121 return Searcher::eCallbackReturnContinue; 122 else 123 return Searcher::eCallbackReturnStop; 124 } 125 126 lldb::SearchDepth 127 BreakpointResolverScripted::GetDepth() { 128 assert(m_breakpoint != nullptr); 129 lldb::SearchDepth depth = lldb::eSearchDepthModule; 130 if (m_implementation_sp) { 131 ScriptInterpreter *interp = GetScriptInterpreter(); 132 depth = interp->ScriptedBreakpointResolverSearchDepth( 133 m_implementation_sp); 134 } 135 return depth; 136 } 137 138 void BreakpointResolverScripted::GetDescription(Stream *s) { 139 StructuredData::GenericSP generic_sp; 140 std::string short_help; 141 142 if (m_implementation_sp) { 143 ScriptInterpreter *interp = GetScriptInterpreter(); 144 interp->GetShortHelpForCommandObject(m_implementation_sp, 145 short_help); 146 } 147 if (!short_help.empty()) 148 s->PutCString(short_help.c_str()); 149 else 150 s->Printf("python class = %s", m_class_name.c_str()); 151 } 152 153 void BreakpointResolverScripted::Dump(Stream *s) const {} 154 155 lldb::BreakpointResolverSP 156 BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) { 157 // FIXME: Have to make a copy of the arguments from the m_args_ptr and then 158 // pass that to the new resolver. 159 lldb::BreakpointResolverSP ret_sp( 160 new BreakpointResolverScripted(&breakpoint, m_class_name, m_depth, 161 nullptr)); 162 return ret_sp; 163 } 164