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