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