1 //===-- BreakpointResolverScripted.cpp ------------------------------------===//
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:
BreakpointResolverScripted(const BreakpointSP & bkpt,const llvm::StringRef class_name,lldb::SearchDepth depth,StructuredDataImpl * args_data)28 BreakpointResolverScripted::BreakpointResolverScripted(
29 const BreakpointSP &bkpt, const llvm::StringRef class_name,
30 lldb::SearchDepth depth, StructuredDataImpl *args_data)
31 : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver),
32 m_class_name(std::string(class_name)), m_depth(depth),
33 m_args_ptr(args_data) {
34 CreateImplementationIfNeeded(bkpt);
35 }
36
CreateImplementationIfNeeded(BreakpointSP breakpoint_sp)37 void BreakpointResolverScripted::CreateImplementationIfNeeded(
38 BreakpointSP breakpoint_sp) {
39 if (m_implementation_sp)
40 return;
41
42 if (m_class_name.empty())
43 return;
44
45 if (!breakpoint_sp)
46 return;
47
48 TargetSP target_sp = breakpoint_sp->GetTargetSP();
49 ScriptInterpreter *script_interp = target_sp->GetDebugger()
50 .GetScriptInterpreter();
51 if (!script_interp)
52 return;
53
54 m_implementation_sp = script_interp->CreateScriptedBreakpointResolver(
55 m_class_name.c_str(), m_args_ptr, breakpoint_sp);
56 }
57
NotifyBreakpointSet()58 void BreakpointResolverScripted::NotifyBreakpointSet() {
59 CreateImplementationIfNeeded(GetBreakpoint());
60 }
61
62 BreakpointResolver *
CreateFromStructuredData(const BreakpointSP & bkpt,const StructuredData::Dictionary & options_dict,Status & error)63 BreakpointResolverScripted::CreateFromStructuredData(
64 const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict,
65 Status &error) {
66 llvm::StringRef class_name;
67 bool success;
68
69 success = options_dict.GetValueForKeyAsString(
70 GetKey(OptionNames::PythonClassName), class_name);
71 if (!success) {
72 error.SetErrorString("BRFL::CFSD: Couldn't find class name entry.");
73 return nullptr;
74 }
75 // The Python function will actually provide the search depth, this is a
76 // placeholder.
77 lldb::SearchDepth depth = lldb::eSearchDepthTarget;
78
79 StructuredDataImpl *args_data_impl = new StructuredDataImpl();
80 StructuredData::Dictionary *args_dict = nullptr;
81 success = options_dict.GetValueForKeyAsDictionary(
82 GetKey(OptionNames::ScriptArgs), args_dict);
83 if (success) {
84 args_data_impl->SetObjectSP(args_dict->shared_from_this());
85 }
86 return new BreakpointResolverScripted(bkpt, class_name, depth,
87 args_data_impl);
88 }
89
90 StructuredData::ObjectSP
SerializeToStructuredData()91 BreakpointResolverScripted::SerializeToStructuredData() {
92 StructuredData::DictionarySP options_dict_sp(
93 new StructuredData::Dictionary());
94
95 options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName),
96 m_class_name);
97 if (m_args_ptr->IsValid())
98 options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs),
99 m_args_ptr->GetObjectSP());
100
101 return WrapOptionsDict(options_dict_sp);
102 }
103
GetScriptInterpreter()104 ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() {
105 return GetBreakpoint()->GetTarget().GetDebugger().GetScriptInterpreter();
106 }
107
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)108 Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
109 SearchFilter &filter, SymbolContext &context, Address *addr) {
110 bool should_continue = true;
111 if (!m_implementation_sp)
112 return Searcher::eCallbackReturnStop;
113
114 ScriptInterpreter *interp = GetScriptInterpreter();
115 should_continue = interp->ScriptedBreakpointResolverSearchCallback(
116 m_implementation_sp,
117 &context);
118 if (should_continue)
119 return Searcher::eCallbackReturnContinue;
120
121 return Searcher::eCallbackReturnStop;
122 }
123
124 lldb::SearchDepth
GetDepth()125 BreakpointResolverScripted::GetDepth() {
126 lldb::SearchDepth depth = lldb::eSearchDepthModule;
127 if (m_implementation_sp) {
128 ScriptInterpreter *interp = GetScriptInterpreter();
129 depth = interp->ScriptedBreakpointResolverSearchDepth(
130 m_implementation_sp);
131 }
132 return depth;
133 }
134
GetDescription(Stream * s)135 void BreakpointResolverScripted::GetDescription(Stream *s) {
136 StructuredData::GenericSP generic_sp;
137 std::string short_help;
138
139 if (m_implementation_sp) {
140 ScriptInterpreter *interp = GetScriptInterpreter();
141 interp->GetShortHelpForCommandObject(m_implementation_sp,
142 short_help);
143 }
144 if (!short_help.empty())
145 s->PutCString(short_help.c_str());
146 else
147 s->Printf("python class = %s", m_class_name.c_str());
148 }
149
Dump(Stream * s) const150 void BreakpointResolverScripted::Dump(Stream *s) const {}
151
152 lldb::BreakpointResolverSP
CopyForBreakpoint(BreakpointSP & breakpoint)153 BreakpointResolverScripted::CopyForBreakpoint(BreakpointSP &breakpoint) {
154 // FIXME: Have to make a copy of the arguments from the m_args_ptr and then
155 // pass that to the new resolver.
156 lldb::BreakpointResolverSP ret_sp(
157 new BreakpointResolverScripted(breakpoint, m_class_name, m_depth,
158 nullptr));
159 return ret_sp;
160 }
161