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