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 
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) {
35   SetIsMasterPlan(true);
36   SetOkayToDiscard(true);
37   SetPrivate(false);
38 }
39 
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 
45 bool ThreadPlanPython::ValidatePlan(Stream *error) {
46   // I have to postpone setting up the implementation till after the constructor
47   // because I need to call
48   // shared_from_this, which you can't do in the constructor.  So I'll do it
49   // here.
50   if (m_implementation_sp)
51     return true;
52   else
53     return false;
54 }
55 
56 void ThreadPlanPython::DidPush() {
57   // We set up the script side in DidPush, so that it can push other plans in
58   // the constructor, and doesn't have to care about the details of DidPush.
59 
60   if (!m_class_name.empty()) {
61     ScriptInterpreter *script_interp = m_thread.GetProcess()
62                                            ->GetTarget()
63                                            .GetDebugger()
64                                            .GetCommandInterpreter()
65                                            .GetScriptInterpreter();
66     if (script_interp) {
67       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
68           m_class_name.c_str(), this->shared_from_this());
69     }
70   }
71 }
72 
73 bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
74   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
75   if (log)
76     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
77                 m_class_name.c_str());
78 
79   bool should_stop = true;
80   if (m_implementation_sp) {
81     ScriptInterpreter *script_interp = m_thread.GetProcess()
82                                            ->GetTarget()
83                                            .GetDebugger()
84                                            .GetCommandInterpreter()
85                                            .GetScriptInterpreter();
86     if (script_interp) {
87       bool script_error;
88       should_stop = script_interp->ScriptedThreadPlanShouldStop(
89           m_implementation_sp, event_ptr, script_error);
90       if (script_error)
91         SetPlanComplete(false);
92     }
93   }
94   return should_stop;
95 }
96 
97 bool ThreadPlanPython::IsPlanStale() {
98   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
99   if (log)
100     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
101                 m_class_name.c_str());
102 
103   bool is_stale = true;
104   if (m_implementation_sp) {
105     ScriptInterpreter *script_interp = m_thread.GetProcess()
106                                            ->GetTarget()
107                                            .GetDebugger()
108                                            .GetCommandInterpreter()
109                                            .GetScriptInterpreter();
110     if (script_interp) {
111       bool script_error;
112       is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
113                                                           script_error);
114       if (script_error)
115         SetPlanComplete(false);
116     }
117   }
118   return is_stale;
119 }
120 
121 bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
122   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
123   if (log)
124     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
125                 m_class_name.c_str());
126 
127   bool explains_stop = true;
128   if (m_implementation_sp) {
129     ScriptInterpreter *script_interp = m_thread.GetProcess()
130                                            ->GetTarget()
131                                            .GetDebugger()
132                                            .GetCommandInterpreter()
133                                            .GetScriptInterpreter();
134     if (script_interp) {
135       bool script_error;
136       explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
137           m_implementation_sp, event_ptr, script_error);
138       if (script_error)
139         SetPlanComplete(false);
140     }
141   }
142   return explains_stop;
143 }
144 
145 bool ThreadPlanPython::MischiefManaged() {
146   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
147   if (log)
148     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
149                 m_class_name.c_str());
150   bool mischief_managed = true;
151   if (m_implementation_sp) {
152     // I don't really need mischief_managed, since it's simpler to just call
153     // SetPlanComplete in should_stop.
154     mischief_managed = IsPlanComplete();
155     if (mischief_managed)
156       m_implementation_sp.reset();
157   }
158   return mischief_managed;
159 }
160 
161 lldb::StateType ThreadPlanPython::GetPlanRunState() {
162   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
163   if (log)
164     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
165                 m_class_name.c_str());
166   lldb::StateType run_state = eStateRunning;
167   if (m_implementation_sp) {
168     ScriptInterpreter *script_interp = m_thread.GetProcess()
169                                            ->GetTarget()
170                                            .GetDebugger()
171                                            .GetCommandInterpreter()
172                                            .GetScriptInterpreter();
173     if (script_interp) {
174       bool script_error;
175       run_state = script_interp->ScriptedThreadPlanGetRunState(
176           m_implementation_sp, script_error);
177     }
178   }
179   return run_state;
180 }
181 
182 // The ones below are not currently exported to Python.
183 
184 bool ThreadPlanPython::StopOthers() {
185   // For now Python plans run all threads, but we should add some controls for
186   // this.
187   return false;
188 }
189 
190 void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
191   s->Printf("Python thread plan implemented by class %s.",
192             m_class_name.c_str());
193 }
194 
195 bool ThreadPlanPython::WillStop() {
196   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
197   if (log)
198     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
199                 m_class_name.c_str());
200   return true;
201 }
202