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 = nullptr; 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 BreakpointResolverScripted::SearchCallback( 127 SearchFilter &filter, SymbolContext &context, Address *addr) { 128 assert(m_breakpoint != nullptr); 129 bool should_continue = true; 130 if (!m_implementation_sp) 131 return Searcher::eCallbackReturnStop; 132 133 ScriptInterpreter *interp = GetScriptInterpreter(); 134 should_continue = interp->ScriptedBreakpointResolverSearchCallback( 135 m_implementation_sp, 136 &context); 137 if (should_continue) 138 return Searcher::eCallbackReturnContinue; 139 else 140 return Searcher::eCallbackReturnStop; 141 } 142 143 lldb::SearchDepth 144 BreakpointResolverScripted::GetDepth() { 145 assert(m_breakpoint != nullptr); 146 lldb::SearchDepth depth = lldb::eSearchDepthModule; 147 if (m_implementation_sp) { 148 ScriptInterpreter *interp = GetScriptInterpreter(); 149 depth = interp->ScriptedBreakpointResolverSearchDepth( 150 m_implementation_sp); 151 } 152 return depth; 153 } 154 155 void BreakpointResolverScripted::GetDescription(Stream *s) { 156 StructuredData::GenericSP generic_sp; 157 std::string short_help; 158 159 if (m_implementation_sp) { 160 ScriptInterpreter *interp = GetScriptInterpreter(); 161 interp->GetShortHelpForCommandObject(m_implementation_sp, 162 short_help); 163 } 164 if (!short_help.empty()) 165 s->PutCString(short_help.c_str()); 166 else 167 s->Printf("python class = %s", m_class_name.c_str()); 168 } 169 170 void BreakpointResolverScripted::Dump(Stream *s) const {} 171 172 lldb::BreakpointResolverSP 173 BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) { 174 ScriptInterpreter *script_interp = GetScriptInterpreter(); 175 // FIXME: Have to make a copy of the arguments from the m_args_ptr and then 176 // pass that to the new resolver. 177 lldb::BreakpointResolverSP ret_sp( 178 new BreakpointResolverScripted(&breakpoint, m_class_name, 179 m_depth, nullptr, *script_interp)); 180 return ret_sp; 181 } 182