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