1 //===-- BreakpointResolverScripted.cpp ------------------------------------===// 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, const llvm::StringRef class_name, lldb::SearchDepth depth, 30 StructuredDataImpl *args_data) 31 : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver), 32 m_class_name(std::string(class_name)), m_depth(depth), 33 m_args_ptr(args_data) { 34 CreateImplementationIfNeeded(); 35 } 36 37 void BreakpointResolverScripted::CreateImplementationIfNeeded() { 38 if (m_implementation_sp) 39 return; 40 41 if (m_class_name.empty()) 42 return; 43 44 if (m_breakpoint) { 45 TargetSP target_sp = m_breakpoint->GetTargetSP(); 46 ScriptInterpreter *script_interp = target_sp->GetDebugger() 47 .GetScriptInterpreter(); 48 if (!script_interp) 49 return; 50 lldb::BreakpointSP bkpt_sp(m_breakpoint->shared_from_this()); 51 m_implementation_sp = script_interp->CreateScriptedBreakpointResolver( 52 m_class_name.c_str(), m_args_ptr, bkpt_sp); 53 } 54 } 55 56 void BreakpointResolverScripted::NotifyBreakpointSet() { 57 CreateImplementationIfNeeded(); 58 } 59 60 BreakpointResolverScripted::~BreakpointResolverScripted() {} 61 62 BreakpointResolver * 63 BreakpointResolverScripted::CreateFromStructuredData( 64 Breakpoint *bkpt, const StructuredData::Dictionary &options_dict, 65 Status &error) { 66 llvm::StringRef class_name; 67 bool success; 68 69 success = options_dict.GetValueForKeyAsString( 70 GetKey(OptionNames::PythonClassName), class_name); 71 if (!success) { 72 error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); 73 return nullptr; 74 } 75 // The Python function will actually provide the search depth, this is a 76 // placeholder. 77 lldb::SearchDepth depth = lldb::eSearchDepthTarget; 78 79 StructuredDataImpl *args_data_impl = new StructuredDataImpl(); 80 StructuredData::Dictionary *args_dict = nullptr; 81 success = options_dict.GetValueForKeyAsDictionary( 82 GetKey(OptionNames::ScriptArgs), args_dict); 83 if (success) { 84 args_data_impl->SetObjectSP(args_dict->shared_from_this()); 85 } 86 return new BreakpointResolverScripted(bkpt, class_name, depth, 87 args_data_impl); 88 } 89 90 StructuredData::ObjectSP 91 BreakpointResolverScripted::SerializeToStructuredData() { 92 StructuredData::DictionarySP options_dict_sp( 93 new StructuredData::Dictionary()); 94 95 options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName), 96 m_class_name); 97 if (m_args_ptr->IsValid()) 98 options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs), 99 m_args_ptr->GetObjectSP()); 100 101 return WrapOptionsDict(options_dict_sp); 102 } 103 104 ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { 105 return m_breakpoint->GetTarget().GetDebugger().GetScriptInterpreter(); 106 } 107 108 Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( 109 SearchFilter &filter, SymbolContext &context, Address *addr) { 110 assert(m_breakpoint != nullptr); 111 bool should_continue = true; 112 if (!m_implementation_sp) 113 return Searcher::eCallbackReturnStop; 114 115 ScriptInterpreter *interp = GetScriptInterpreter(); 116 should_continue = interp->ScriptedBreakpointResolverSearchCallback( 117 m_implementation_sp, 118 &context); 119 if (should_continue) 120 return Searcher::eCallbackReturnContinue; 121 else 122 return Searcher::eCallbackReturnStop; 123 } 124 125 lldb::SearchDepth 126 BreakpointResolverScripted::GetDepth() { 127 assert(m_breakpoint != nullptr); 128 lldb::SearchDepth depth = lldb::eSearchDepthModule; 129 if (m_implementation_sp) { 130 ScriptInterpreter *interp = GetScriptInterpreter(); 131 depth = interp->ScriptedBreakpointResolverSearchDepth( 132 m_implementation_sp); 133 } 134 return depth; 135 } 136 137 void BreakpointResolverScripted::GetDescription(Stream *s) { 138 StructuredData::GenericSP generic_sp; 139 std::string short_help; 140 141 if (m_implementation_sp) { 142 ScriptInterpreter *interp = GetScriptInterpreter(); 143 interp->GetShortHelpForCommandObject(m_implementation_sp, 144 short_help); 145 } 146 if (!short_help.empty()) 147 s->PutCString(short_help.c_str()); 148 else 149 s->Printf("python class = %s", m_class_name.c_str()); 150 } 151 152 void BreakpointResolverScripted::Dump(Stream *s) const {} 153 154 lldb::BreakpointResolverSP 155 BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) { 156 // FIXME: Have to make a copy of the arguments from the m_args_ptr and then 157 // pass that to the new resolver. 158 lldb::BreakpointResolverSP ret_sp( 159 new BreakpointResolverScripted(&breakpoint, m_class_name, m_depth, 160 nullptr)); 161 return ret_sp; 162 } 163