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