1e19adf54SJim Ingham //===-- BreakpointResolverScripted.cpp ---------------------------*- C++ -*-===// 2e19adf54SJim Ingham // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e19adf54SJim Ingham // 7e19adf54SJim Ingham //===----------------------------------------------------------------------===// 8e19adf54SJim Ingham 9e19adf54SJim Ingham #include "lldb/Breakpoint/BreakpointResolverScripted.h" 10e19adf54SJim Ingham 11e19adf54SJim Ingham 12e19adf54SJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h" 13e19adf54SJim Ingham #include "lldb/Core/Debugger.h" 14e19adf54SJim Ingham #include "lldb/Core/Module.h" 15e19adf54SJim Ingham #include "lldb/Core/Section.h" 16e19adf54SJim Ingham #include "lldb/Core/StructuredDataImpl.h" 17e19adf54SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 18e19adf54SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h" 19e19adf54SJim Ingham #include "lldb/Target/Process.h" 20e19adf54SJim Ingham #include "lldb/Target/Target.h" 21e19adf54SJim Ingham #include "lldb/Utility/Log.h" 22e19adf54SJim Ingham #include "lldb/Utility/StreamString.h" 23e19adf54SJim Ingham 24e19adf54SJim Ingham using namespace lldb; 25e19adf54SJim Ingham using namespace lldb_private; 26e19adf54SJim Ingham 27e19adf54SJim Ingham // BreakpointResolverScripted: 28e19adf54SJim Ingham BreakpointResolverScripted::BreakpointResolverScripted( 29e19adf54SJim Ingham Breakpoint *bkpt, 30e19adf54SJim Ingham const llvm::StringRef class_name, 31e19adf54SJim Ingham lldb::SearchDepth depth, 32e19adf54SJim Ingham StructuredDataImpl *args_data, 33e19adf54SJim Ingham ScriptInterpreter &script_interp) 34e19adf54SJim Ingham : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver), 35e19adf54SJim Ingham m_class_name(class_name), m_depth(depth), m_args_ptr(args_data) { 36e19adf54SJim Ingham CreateImplementationIfNeeded(); 37e19adf54SJim Ingham } 38e19adf54SJim Ingham 39e19adf54SJim Ingham void BreakpointResolverScripted::CreateImplementationIfNeeded() { 40e19adf54SJim Ingham if (m_implementation_sp) 41e19adf54SJim Ingham return; 42e19adf54SJim Ingham 43e19adf54SJim Ingham if (m_class_name.empty()) 44e19adf54SJim Ingham return; 45e19adf54SJim Ingham 46e19adf54SJim Ingham if (m_breakpoint) { 47e19adf54SJim Ingham TargetSP target_sp = m_breakpoint->GetTargetSP(); 48e19adf54SJim Ingham ScriptInterpreter *script_interp = target_sp->GetDebugger() 49e19adf54SJim Ingham .GetScriptInterpreter(); 50e19adf54SJim Ingham if (!script_interp) 51e19adf54SJim Ingham return; 52e19adf54SJim Ingham lldb::BreakpointSP bkpt_sp(m_breakpoint->shared_from_this()); 53e19adf54SJim Ingham m_implementation_sp = script_interp->CreateScriptedBreakpointResolver( 54e19adf54SJim Ingham m_class_name.c_str(), m_args_ptr, bkpt_sp); 55e19adf54SJim Ingham } 56e19adf54SJim Ingham } 57e19adf54SJim Ingham 58e19adf54SJim Ingham void BreakpointResolverScripted::NotifyBreakpointSet() { 59e19adf54SJim Ingham CreateImplementationIfNeeded(); 60e19adf54SJim Ingham } 61e19adf54SJim Ingham 62e19adf54SJim Ingham BreakpointResolverScripted::~BreakpointResolverScripted() {} 63e19adf54SJim Ingham 64e19adf54SJim Ingham BreakpointResolver * 65e19adf54SJim Ingham BreakpointResolverScripted::CreateFromStructuredData( 66e19adf54SJim Ingham Breakpoint *bkpt, const StructuredData::Dictionary &options_dict, 67e19adf54SJim Ingham Status &error) { 68e19adf54SJim Ingham llvm::StringRef class_name; 69e19adf54SJim Ingham bool success; 70e19adf54SJim Ingham 71e19adf54SJim Ingham if (!bkpt) 72e19adf54SJim Ingham return nullptr; 73e19adf54SJim Ingham 74e19adf54SJim Ingham success = options_dict.GetValueForKeyAsString( 75e19adf54SJim Ingham GetKey(OptionNames::PythonClassName), class_name); 76e19adf54SJim Ingham if (!success) { 77e19adf54SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); 78e19adf54SJim Ingham return nullptr; 79e19adf54SJim Ingham } 80e19adf54SJim Ingham lldb::SearchDepth depth; 81e19adf54SJim Ingham int depth_as_int; 82e19adf54SJim Ingham success = options_dict.GetValueForKeyAsInteger( 83e19adf54SJim Ingham GetKey(OptionNames::SearchDepth), depth_as_int); 84e19adf54SJim Ingham if (!success) { 85e19adf54SJim Ingham error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); 86e19adf54SJim Ingham return nullptr; 87e19adf54SJim Ingham } 88e19adf54SJim Ingham if (depth_as_int >= (int) OptionNames::LastOptionName) { 89e19adf54SJim Ingham error.SetErrorString("BRFL::CFSD: Invalid value for search depth."); 90e19adf54SJim Ingham return nullptr; 91e19adf54SJim Ingham } 92e19adf54SJim Ingham depth = (lldb::SearchDepth) depth_as_int; 93e19adf54SJim Ingham 94e19adf54SJim Ingham StructuredDataImpl *args_data_impl = new StructuredDataImpl(); 956d7fb299SKonrad Kleine StructuredData::Dictionary *args_dict = nullptr; 96e19adf54SJim Ingham success = options_dict.GetValueForKeyAsDictionary( 97e19adf54SJim Ingham GetKey(OptionNames::ScriptArgs), args_dict); 98e19adf54SJim Ingham if (success) { 99e19adf54SJim Ingham // FIXME: The resolver needs a copy of the ARGS dict that it can own, 100e19adf54SJim Ingham // so I need to make a copy constructor for the Dictionary so I can pass 101e19adf54SJim Ingham // that to it here. For now the args are empty. 102e19adf54SJim Ingham //StructuredData::Dictionary *dict_copy = new StructuredData::Dictionary(args_dict); 103e19adf54SJim Ingham 104e19adf54SJim Ingham } 105e19adf54SJim Ingham ScriptInterpreter *script_interp = bkpt->GetTarget() 106e19adf54SJim Ingham .GetDebugger() 107e19adf54SJim Ingham .GetScriptInterpreter(); 108e19adf54SJim Ingham return new BreakpointResolverScripted(bkpt, class_name, depth, args_data_impl, 109e19adf54SJim Ingham *script_interp); 110e19adf54SJim Ingham } 111e19adf54SJim Ingham 112e19adf54SJim Ingham StructuredData::ObjectSP 113e19adf54SJim Ingham BreakpointResolverScripted::SerializeToStructuredData() { 114e19adf54SJim Ingham StructuredData::DictionarySP options_dict_sp( 115e19adf54SJim Ingham new StructuredData::Dictionary()); 116e19adf54SJim Ingham 117e19adf54SJim Ingham options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName), 118e19adf54SJim Ingham m_class_name); 119e19adf54SJim Ingham return WrapOptionsDict(options_dict_sp); 120e19adf54SJim Ingham } 121e19adf54SJim Ingham 122e19adf54SJim Ingham ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { 1232b29b432SJonas Devlieghere return m_breakpoint->GetTarget().GetDebugger().GetScriptInterpreter(); 124e19adf54SJim Ingham } 125e19adf54SJim Ingham 126*95e264fcSRaphael Isemann Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( 127*95e264fcSRaphael Isemann SearchFilter &filter, SymbolContext &context, Address *addr) { 128248a1305SKonrad Kleine assert(m_breakpoint != nullptr); 129e19adf54SJim Ingham bool should_continue = true; 130e19adf54SJim Ingham if (!m_implementation_sp) 131e19adf54SJim Ingham return Searcher::eCallbackReturnStop; 132e19adf54SJim Ingham 133e19adf54SJim Ingham ScriptInterpreter *interp = GetScriptInterpreter(); 134e19adf54SJim Ingham should_continue = interp->ScriptedBreakpointResolverSearchCallback( 135e19adf54SJim Ingham m_implementation_sp, 136e19adf54SJim Ingham &context); 137e19adf54SJim Ingham if (should_continue) 138e19adf54SJim Ingham return Searcher::eCallbackReturnContinue; 139e19adf54SJim Ingham else 140e19adf54SJim Ingham return Searcher::eCallbackReturnStop; 141e19adf54SJim Ingham } 142e19adf54SJim Ingham 143e19adf54SJim Ingham lldb::SearchDepth 144e19adf54SJim Ingham BreakpointResolverScripted::GetDepth() { 145248a1305SKonrad Kleine assert(m_breakpoint != nullptr); 146e19adf54SJim Ingham lldb::SearchDepth depth = lldb::eSearchDepthModule; 147e19adf54SJim Ingham if (m_implementation_sp) { 148e19adf54SJim Ingham ScriptInterpreter *interp = GetScriptInterpreter(); 149e19adf54SJim Ingham depth = interp->ScriptedBreakpointResolverSearchDepth( 150e19adf54SJim Ingham m_implementation_sp); 151e19adf54SJim Ingham } 152e19adf54SJim Ingham return depth; 153e19adf54SJim Ingham } 154e19adf54SJim Ingham 155e19adf54SJim Ingham void BreakpointResolverScripted::GetDescription(Stream *s) { 156e19adf54SJim Ingham StructuredData::GenericSP generic_sp; 157e19adf54SJim Ingham std::string short_help; 158e19adf54SJim Ingham 159e19adf54SJim Ingham if (m_implementation_sp) { 160e19adf54SJim Ingham ScriptInterpreter *interp = GetScriptInterpreter(); 161e19adf54SJim Ingham interp->GetShortHelpForCommandObject(m_implementation_sp, 162e19adf54SJim Ingham short_help); 163e19adf54SJim Ingham } 164e19adf54SJim Ingham if (!short_help.empty()) 165e19adf54SJim Ingham s->PutCString(short_help.c_str()); 166e19adf54SJim Ingham else 167e19adf54SJim Ingham s->Printf("python class = %s", m_class_name.c_str()); 168e19adf54SJim Ingham } 169e19adf54SJim Ingham 170e19adf54SJim Ingham void BreakpointResolverScripted::Dump(Stream *s) const {} 171e19adf54SJim Ingham 172e19adf54SJim Ingham lldb::BreakpointResolverSP 173e19adf54SJim Ingham BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) { 174e19adf54SJim Ingham ScriptInterpreter *script_interp = GetScriptInterpreter(); 175e19adf54SJim Ingham // FIXME: Have to make a copy of the arguments from the m_args_ptr and then 176e19adf54SJim Ingham // pass that to the new resolver. 177e19adf54SJim Ingham lldb::BreakpointResolverSP ret_sp( 178e19adf54SJim Ingham new BreakpointResolverScripted(&breakpoint, m_class_name, 179e19adf54SJim Ingham m_depth, nullptr, *script_interp)); 180e19adf54SJim Ingham return ret_sp; 181e19adf54SJim Ingham } 182