1*0b57cec5SDimitry Andric //===-- BreakpointResolverScripted.cpp ------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointResolverScripted.h"
10*0b57cec5SDimitry Andric 
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
13*0b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
14*0b57cec5SDimitry Andric #include "lldb/Core/Module.h"
15*0b57cec5SDimitry Andric #include "lldb/Core/Section.h"
16*0b57cec5SDimitry Andric #include "lldb/Core/StructuredDataImpl.h"
17*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
18*0b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
19*0b57cec5SDimitry Andric #include "lldb/Target/Process.h"
20*0b57cec5SDimitry Andric #include "lldb/Target/Target.h"
21*0b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
22*0b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric using namespace lldb;
25*0b57cec5SDimitry Andric using namespace lldb_private;
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric // BreakpointResolverScripted:
BreakpointResolverScripted(const BreakpointSP & bkpt,const llvm::StringRef class_name,lldb::SearchDepth depth,StructuredDataImpl * args_data)28*0b57cec5SDimitry Andric BreakpointResolverScripted::BreakpointResolverScripted(
29*0b57cec5SDimitry Andric     const BreakpointSP &bkpt, const llvm::StringRef class_name,
30*0b57cec5SDimitry Andric     lldb::SearchDepth depth, StructuredDataImpl *args_data)
31*0b57cec5SDimitry Andric     : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver),
32*0b57cec5SDimitry Andric       m_class_name(std::string(class_name)), m_depth(depth),
33*0b57cec5SDimitry Andric       m_args_ptr(args_data) {
34*0b57cec5SDimitry Andric   CreateImplementationIfNeeded(bkpt);
35*0b57cec5SDimitry Andric }
36*0b57cec5SDimitry Andric 
CreateImplementationIfNeeded(BreakpointSP breakpoint_sp)37*0b57cec5SDimitry Andric void BreakpointResolverScripted::CreateImplementationIfNeeded(
38*0b57cec5SDimitry Andric     BreakpointSP breakpoint_sp) {
39*0b57cec5SDimitry Andric   if (m_implementation_sp)
40*0b57cec5SDimitry Andric     return;
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric   if (m_class_name.empty())
43*0b57cec5SDimitry Andric     return;
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric   if (!breakpoint_sp)
46*0b57cec5SDimitry Andric     return;
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric   TargetSP target_sp = breakpoint_sp->GetTargetSP();
49*0b57cec5SDimitry Andric   ScriptInterpreter *script_interp = target_sp->GetDebugger()
50*0b57cec5SDimitry Andric                                               .GetScriptInterpreter();
51*0b57cec5SDimitry Andric   if (!script_interp)
52*0b57cec5SDimitry Andric     return;
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   m_implementation_sp = script_interp->CreateScriptedBreakpointResolver(
55*0b57cec5SDimitry Andric       m_class_name.c_str(), m_args_ptr, breakpoint_sp);
56*0b57cec5SDimitry Andric }
57*0b57cec5SDimitry Andric 
NotifyBreakpointSet()58*0b57cec5SDimitry Andric void BreakpointResolverScripted::NotifyBreakpointSet() {
59*0b57cec5SDimitry Andric   CreateImplementationIfNeeded(GetBreakpoint());
60*0b57cec5SDimitry Andric }
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric BreakpointResolver *
CreateFromStructuredData(const BreakpointSP & bkpt,const StructuredData::Dictionary & options_dict,Status & error)63*0b57cec5SDimitry Andric BreakpointResolverScripted::CreateFromStructuredData(
64*0b57cec5SDimitry Andric     const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict,
65*0b57cec5SDimitry Andric     Status &error) {
66*0b57cec5SDimitry Andric   llvm::StringRef class_name;
67*0b57cec5SDimitry Andric   bool success;
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric   success = options_dict.GetValueForKeyAsString(
70*0b57cec5SDimitry Andric       GetKey(OptionNames::PythonClassName), class_name);
71*0b57cec5SDimitry Andric   if (!success) {
72*0b57cec5SDimitry Andric     error.SetErrorString("BRFL::CFSD: Couldn't find class name entry.");
73*0b57cec5SDimitry Andric     return nullptr;
74*0b57cec5SDimitry Andric   }
75*0b57cec5SDimitry Andric   // The Python function will actually provide the search depth, this is a
76*0b57cec5SDimitry Andric   // placeholder.
77*0b57cec5SDimitry Andric   lldb::SearchDepth depth = lldb::eSearchDepthTarget;
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric   StructuredDataImpl *args_data_impl = new StructuredDataImpl();
80*0b57cec5SDimitry Andric   StructuredData::Dictionary *args_dict = nullptr;
81*0b57cec5SDimitry Andric   success = options_dict.GetValueForKeyAsDictionary(
82*0b57cec5SDimitry Andric     GetKey(OptionNames::ScriptArgs), args_dict);
83*0b57cec5SDimitry Andric   if (success) {
84*0b57cec5SDimitry Andric       args_data_impl->SetObjectSP(args_dict->shared_from_this());
85*0b57cec5SDimitry Andric   }
86*0b57cec5SDimitry Andric   return new BreakpointResolverScripted(bkpt, class_name, depth,
87*0b57cec5SDimitry Andric                                         args_data_impl);
88*0b57cec5SDimitry Andric }
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric StructuredData::ObjectSP
SerializeToStructuredData()91*0b57cec5SDimitry Andric BreakpointResolverScripted::SerializeToStructuredData() {
92*0b57cec5SDimitry Andric   StructuredData::DictionarySP options_dict_sp(
93*0b57cec5SDimitry Andric       new StructuredData::Dictionary());
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric   options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName),
96*0b57cec5SDimitry Andric                                    m_class_name);
97*0b57cec5SDimitry Andric   if (m_args_ptr->IsValid())
98*0b57cec5SDimitry Andric       options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs),
99*0b57cec5SDimitry Andric           m_args_ptr->GetObjectSP());
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   return WrapOptionsDict(options_dict_sp);
102*0b57cec5SDimitry Andric }
103*0b57cec5SDimitry Andric 
GetScriptInterpreter()104*0b57cec5SDimitry Andric ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() {
105*0b57cec5SDimitry Andric   return GetBreakpoint()->GetTarget().GetDebugger().GetScriptInterpreter();
106*0b57cec5SDimitry Andric }
107*0b57cec5SDimitry Andric 
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)108*0b57cec5SDimitry Andric Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
109*0b57cec5SDimitry Andric     SearchFilter &filter, SymbolContext &context, Address *addr) {
110*0b57cec5SDimitry Andric   bool should_continue = true;
111*0b57cec5SDimitry Andric   if (!m_implementation_sp)
112*0b57cec5SDimitry Andric     return Searcher::eCallbackReturnStop;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   ScriptInterpreter *interp = GetScriptInterpreter();
115*0b57cec5SDimitry Andric   should_continue = interp->ScriptedBreakpointResolverSearchCallback(
116*0b57cec5SDimitry Andric       m_implementation_sp,
117*0b57cec5SDimitry Andric       &context);
118*0b57cec5SDimitry Andric   if (should_continue)
119*0b57cec5SDimitry Andric     return Searcher::eCallbackReturnContinue;
120*0b57cec5SDimitry Andric 
121*0b57cec5SDimitry Andric   return Searcher::eCallbackReturnStop;
122*0b57cec5SDimitry Andric }
123*0b57cec5SDimitry Andric 
124*0b57cec5SDimitry Andric lldb::SearchDepth
GetDepth()125*0b57cec5SDimitry Andric BreakpointResolverScripted::GetDepth() {
126*0b57cec5SDimitry Andric   lldb::SearchDepth depth = lldb::eSearchDepthModule;
127*0b57cec5SDimitry Andric   if (m_implementation_sp) {
128*0b57cec5SDimitry Andric     ScriptInterpreter *interp = GetScriptInterpreter();
129*0b57cec5SDimitry Andric     depth = interp->ScriptedBreakpointResolverSearchDepth(
130*0b57cec5SDimitry Andric         m_implementation_sp);
131*0b57cec5SDimitry Andric   }
132*0b57cec5SDimitry Andric   return depth;
133*0b57cec5SDimitry Andric }
134*0b57cec5SDimitry Andric 
GetDescription(Stream * s)135*0b57cec5SDimitry Andric void BreakpointResolverScripted::GetDescription(Stream *s) {
136*0b57cec5SDimitry Andric   StructuredData::GenericSP generic_sp;
137*0b57cec5SDimitry Andric   std::string short_help;
138*0b57cec5SDimitry Andric 
139*0b57cec5SDimitry Andric   if (m_implementation_sp) {
140*0b57cec5SDimitry Andric     ScriptInterpreter *interp = GetScriptInterpreter();
141*0b57cec5SDimitry Andric     interp->GetShortHelpForCommandObject(m_implementation_sp,
142*0b57cec5SDimitry Andric                                          short_help);
143*0b57cec5SDimitry Andric   }
144*0b57cec5SDimitry Andric   if (!short_help.empty())
145*0b57cec5SDimitry Andric     s->PutCString(short_help.c_str());
146*0b57cec5SDimitry Andric   else
147*0b57cec5SDimitry Andric     s->Printf("python class = %s", m_class_name.c_str());
148*0b57cec5SDimitry Andric }
149*0b57cec5SDimitry Andric 
Dump(Stream * s) const150*0b57cec5SDimitry Andric void BreakpointResolverScripted::Dump(Stream *s) const {}
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric lldb::BreakpointResolverSP
CopyForBreakpoint(BreakpointSP & breakpoint)153*0b57cec5SDimitry Andric BreakpointResolverScripted::CopyForBreakpoint(BreakpointSP &breakpoint) {
154*0b57cec5SDimitry Andric   // FIXME: Have to make a copy of the arguments from the m_args_ptr and then
155*0b57cec5SDimitry Andric   // pass that to the new resolver.
156*0b57cec5SDimitry Andric   lldb::BreakpointResolverSP ret_sp(
157*0b57cec5SDimitry Andric       new BreakpointResolverScripted(breakpoint, m_class_name, m_depth,
158*0b57cec5SDimitry Andric                                      nullptr));
159*0b57cec5SDimitry Andric   return ret_sp;
160*0b57cec5SDimitry Andric }
161*0b57cec5SDimitry Andric