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