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.SetErrorString("BRFL::CFSD: Couldn't find class name entry." ); |
70 | return nullptr; |
71 | } |
72 | // The Python function will actually provide the search depth, this is a |
73 | // placeholder. |
74 | lldb::SearchDepth depth = lldb::eSearchDepthTarget; |
75 | |
76 | StructuredDataImpl args_data_impl; |
77 | StructuredData::Dictionary *args_dict = nullptr; |
78 | if (options_dict.GetValueForKeyAsDictionary(key: GetKey(enum_value: OptionNames::ScriptArgs), |
79 | result&: args_dict)) |
80 | args_data_impl.SetObjectSP(args_dict->shared_from_this()); |
81 | return std::make_shared<BreakpointResolverScripted>(args: nullptr, args&: class_name, |
82 | args&: depth, args&: args_data_impl); |
83 | } |
84 | |
85 | StructuredData::ObjectSP |
86 | BreakpointResolverScripted::SerializeToStructuredData() { |
87 | StructuredData::DictionarySP options_dict_sp( |
88 | new StructuredData::Dictionary()); |
89 | |
90 | options_dict_sp->AddStringItem(key: GetKey(enum_value: OptionNames::PythonClassName), |
91 | value: m_class_name); |
92 | if (m_args.IsValid()) |
93 | options_dict_sp->AddItem(key: GetKey(enum_value: OptionNames::ScriptArgs), |
94 | value_sp: m_args.GetObjectSP()); |
95 | |
96 | return WrapOptionsDict(options_dict_sp); |
97 | } |
98 | |
99 | ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { |
100 | return GetBreakpoint()->GetTarget().GetDebugger().GetScriptInterpreter(); |
101 | } |
102 | |
103 | Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback( |
104 | SearchFilter &filter, SymbolContext &context, Address *addr) { |
105 | bool should_continue = true; |
106 | if (!m_implementation_sp) |
107 | return Searcher::eCallbackReturnStop; |
108 | |
109 | ScriptInterpreter *interp = GetScriptInterpreter(); |
110 | should_continue = interp->ScriptedBreakpointResolverSearchCallback( |
111 | implementor_sp: m_implementation_sp, |
112 | sym_ctx: &context); |
113 | if (should_continue) |
114 | return Searcher::eCallbackReturnContinue; |
115 | |
116 | return Searcher::eCallbackReturnStop; |
117 | } |
118 | |
119 | lldb::SearchDepth |
120 | BreakpointResolverScripted::GetDepth() { |
121 | lldb::SearchDepth depth = lldb::eSearchDepthModule; |
122 | if (m_implementation_sp) { |
123 | ScriptInterpreter *interp = GetScriptInterpreter(); |
124 | depth = interp->ScriptedBreakpointResolverSearchDepth( |
125 | implementor_sp: m_implementation_sp); |
126 | } |
127 | return depth; |
128 | } |
129 | |
130 | void BreakpointResolverScripted::GetDescription(Stream *s) { |
131 | StructuredData::GenericSP generic_sp; |
132 | std::string short_help; |
133 | |
134 | if (m_implementation_sp) { |
135 | ScriptInterpreter *interp = GetScriptInterpreter(); |
136 | interp->GetShortHelpForCommandObject(cmd_obj_sp: m_implementation_sp, |
137 | dest&: short_help); |
138 | } |
139 | if (!short_help.empty()) |
140 | s->PutCString(cstr: short_help.c_str()); |
141 | else |
142 | s->Printf(format: "python class = %s" , m_class_name.c_str()); |
143 | } |
144 | |
145 | void BreakpointResolverScripted::Dump(Stream *s) const {} |
146 | |
147 | lldb::BreakpointResolverSP |
148 | BreakpointResolverScripted::CopyForBreakpoint(BreakpointSP &breakpoint) { |
149 | return std::make_shared<BreakpointResolverScripted>(args&: breakpoint, args&: m_class_name, |
150 | args&: m_depth, args&: m_args); |
151 | } |
152 | |