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