1 //===-- ThreadPlanPython.cpp ------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Target/ThreadPlan.h"
11
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Interpreter/CommandInterpreter.h"
14 #include "lldb/Interpreter/ScriptInterpreter.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Target/RegisterContext.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Target/Thread.h"
19 #include "lldb/Target/ThreadPlan.h"
20 #include "lldb/Target/ThreadPlanPython.h"
21 #include "lldb/Utility/Log.h"
22 #include "lldb/Utility/State.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 //----------------------------------------------------------------------
28 // ThreadPlanPython
29 //----------------------------------------------------------------------
30
ThreadPlanPython(Thread & thread,const char * class_name)31 ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
32 : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
33 eVoteNoOpinion, eVoteNoOpinion),
34 m_class_name(class_name), m_did_push(false) {
35 SetIsMasterPlan(true);
36 SetOkayToDiscard(true);
37 SetPrivate(false);
38 }
39
~ThreadPlanPython()40 ThreadPlanPython::~ThreadPlanPython() {
41 // FIXME, do I need to decrement the ref count on this implementation object
42 // to make it go away?
43 }
44
ValidatePlan(Stream * error)45 bool ThreadPlanPython::ValidatePlan(Stream *error) {
46 if (!m_did_push)
47 return true;
48
49 if (!m_implementation_sp) {
50 if (error)
51 error->Printf("Python thread plan does not have an implementation");
52 return false;
53 }
54
55 return true;
56 }
57
DidPush()58 void ThreadPlanPython::DidPush() {
59 // We set up the script side in DidPush, so that it can push other plans in
60 // the constructor, and doesn't have to care about the details of DidPush.
61 m_did_push = true;
62 if (!m_class_name.empty()) {
63 ScriptInterpreter *script_interp = m_thread.GetProcess()
64 ->GetTarget()
65 .GetDebugger()
66 .GetCommandInterpreter()
67 .GetScriptInterpreter();
68 if (script_interp) {
69 m_implementation_sp = script_interp->CreateScriptedThreadPlan(
70 m_class_name.c_str(), this->shared_from_this());
71 }
72 }
73 }
74
ShouldStop(Event * event_ptr)75 bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
76 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
77 if (log)
78 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
79 m_class_name.c_str());
80
81 bool should_stop = true;
82 if (m_implementation_sp) {
83 ScriptInterpreter *script_interp = m_thread.GetProcess()
84 ->GetTarget()
85 .GetDebugger()
86 .GetCommandInterpreter()
87 .GetScriptInterpreter();
88 if (script_interp) {
89 bool script_error;
90 should_stop = script_interp->ScriptedThreadPlanShouldStop(
91 m_implementation_sp, event_ptr, script_error);
92 if (script_error)
93 SetPlanComplete(false);
94 }
95 }
96 return should_stop;
97 }
98
IsPlanStale()99 bool ThreadPlanPython::IsPlanStale() {
100 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
101 if (log)
102 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
103 m_class_name.c_str());
104
105 bool is_stale = true;
106 if (m_implementation_sp) {
107 ScriptInterpreter *script_interp = m_thread.GetProcess()
108 ->GetTarget()
109 .GetDebugger()
110 .GetCommandInterpreter()
111 .GetScriptInterpreter();
112 if (script_interp) {
113 bool script_error;
114 is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
115 script_error);
116 if (script_error)
117 SetPlanComplete(false);
118 }
119 }
120 return is_stale;
121 }
122
DoPlanExplainsStop(Event * event_ptr)123 bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
124 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
125 if (log)
126 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
127 m_class_name.c_str());
128
129 bool explains_stop = true;
130 if (m_implementation_sp) {
131 ScriptInterpreter *script_interp = m_thread.GetProcess()
132 ->GetTarget()
133 .GetDebugger()
134 .GetCommandInterpreter()
135 .GetScriptInterpreter();
136 if (script_interp) {
137 bool script_error;
138 explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
139 m_implementation_sp, event_ptr, script_error);
140 if (script_error)
141 SetPlanComplete(false);
142 }
143 }
144 return explains_stop;
145 }
146
MischiefManaged()147 bool ThreadPlanPython::MischiefManaged() {
148 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
149 if (log)
150 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
151 m_class_name.c_str());
152 bool mischief_managed = true;
153 if (m_implementation_sp) {
154 // I don't really need mischief_managed, since it's simpler to just call
155 // SetPlanComplete in should_stop.
156 mischief_managed = IsPlanComplete();
157 if (mischief_managed)
158 m_implementation_sp.reset();
159 }
160 return mischief_managed;
161 }
162
GetPlanRunState()163 lldb::StateType ThreadPlanPython::GetPlanRunState() {
164 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
165 if (log)
166 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
167 m_class_name.c_str());
168 lldb::StateType run_state = eStateRunning;
169 if (m_implementation_sp) {
170 ScriptInterpreter *script_interp = m_thread.GetProcess()
171 ->GetTarget()
172 .GetDebugger()
173 .GetCommandInterpreter()
174 .GetScriptInterpreter();
175 if (script_interp) {
176 bool script_error;
177 run_state = script_interp->ScriptedThreadPlanGetRunState(
178 m_implementation_sp, script_error);
179 }
180 }
181 return run_state;
182 }
183
184 // The ones below are not currently exported to Python.
185
StopOthers()186 bool ThreadPlanPython::StopOthers() {
187 // For now Python plans run all threads, but we should add some controls for
188 // this.
189 return false;
190 }
191
GetDescription(Stream * s,lldb::DescriptionLevel level)192 void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
193 s->Printf("Python thread plan implemented by class %s.",
194 m_class_name.c_str());
195 }
196
WillStop()197 bool ThreadPlanPython::WillStop() {
198 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
199 if (log)
200 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
201 m_class_name.c_str());
202 return true;
203 }
204