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