12bdbfd50SJim Ingham //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
22bdbfd50SJim Ingham //
32bdbfd50SJim Ingham //                     The LLVM Compiler Infrastructure
42bdbfd50SJim Ingham //
52bdbfd50SJim Ingham // This file is distributed under the University of Illinois Open Source
62bdbfd50SJim Ingham // License. See LICENSE.TXT for details.
72bdbfd50SJim Ingham //
82bdbfd50SJim Ingham //===----------------------------------------------------------------------===//
92bdbfd50SJim Ingham 
102bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
112bdbfd50SJim Ingham 
122bdbfd50SJim Ingham // C Includes
132bdbfd50SJim Ingham // C++ Includes
142bdbfd50SJim Ingham // Other libraries and framework includes
152bdbfd50SJim Ingham // Project includes
162bdbfd50SJim Ingham #include "lldb/Core/Debugger.h"
172bdbfd50SJim Ingham #include "lldb/Core/Log.h"
182bdbfd50SJim Ingham #include "lldb/Core/State.h"
192bdbfd50SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
202bdbfd50SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h"
21*b9c1b51eSKate Stone #include "lldb/Target/Process.h"
222bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h"
23*b9c1b51eSKate Stone #include "lldb/Target/Target.h"
242bdbfd50SJim Ingham #include "lldb/Target/Thread.h"
252bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
262bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h"
272bdbfd50SJim Ingham 
282bdbfd50SJim Ingham using namespace lldb;
292bdbfd50SJim Ingham using namespace lldb_private;
302bdbfd50SJim Ingham 
312bdbfd50SJim Ingham //----------------------------------------------------------------------
322bdbfd50SJim Ingham // ThreadPlanPython
332bdbfd50SJim Ingham //----------------------------------------------------------------------
342bdbfd50SJim Ingham 
35*b9c1b51eSKate Stone ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
36*b9c1b51eSKate Stone     : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
37*b9c1b51eSKate Stone                  eVoteNoOpinion, eVoteNoOpinion),
38*b9c1b51eSKate Stone       m_class_name(class_name) {
392bdbfd50SJim Ingham   SetIsMasterPlan(true);
402bdbfd50SJim Ingham   SetOkayToDiscard(true);
412bdbfd50SJim Ingham   SetPrivate(false);
422bdbfd50SJim Ingham }
432bdbfd50SJim Ingham 
44*b9c1b51eSKate Stone ThreadPlanPython::~ThreadPlanPython() {
45*b9c1b51eSKate Stone   // FIXME, do I need to decrement the ref count on this implementation object
46*b9c1b51eSKate Stone   // to make it go away?
472bdbfd50SJim Ingham }
482bdbfd50SJim Ingham 
49*b9c1b51eSKate Stone bool ThreadPlanPython::ValidatePlan(Stream *error) {
50*b9c1b51eSKate Stone   // I have to postpone setting up the implementation till after the constructor
51*b9c1b51eSKate Stone   // because I need to call
52*b9c1b51eSKate Stone   // shared_from_this, which you can't do in the constructor.  So I'll do it
53*b9c1b51eSKate Stone   // here.
542bdbfd50SJim Ingham   if (m_implementation_sp)
552bdbfd50SJim Ingham     return true;
562bdbfd50SJim Ingham   else
572bdbfd50SJim Ingham     return false;
582bdbfd50SJim Ingham }
592bdbfd50SJim Ingham 
60*b9c1b51eSKate Stone void ThreadPlanPython::DidPush() {
61*b9c1b51eSKate Stone   // We set up the script side in DidPush, so that it can push other plans in
62*b9c1b51eSKate Stone   // the constructor,
632bdbfd50SJim Ingham   // and doesn't have to care about the details of DidPush.
642bdbfd50SJim Ingham 
65*b9c1b51eSKate Stone   if (!m_class_name.empty()) {
66*b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
67*b9c1b51eSKate Stone                                            ->GetTarget()
68*b9c1b51eSKate Stone                                            .GetDebugger()
69*b9c1b51eSKate Stone                                            .GetCommandInterpreter()
70*b9c1b51eSKate Stone                                            .GetScriptInterpreter();
71*b9c1b51eSKate Stone     if (script_interp) {
72*b9c1b51eSKate Stone       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
73*b9c1b51eSKate Stone           m_class_name.c_str(), this->shared_from_this());
742bdbfd50SJim Ingham     }
752bdbfd50SJim Ingham   }
762bdbfd50SJim Ingham }
772bdbfd50SJim Ingham 
78*b9c1b51eSKate Stone bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
792bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
802bdbfd50SJim Ingham   if (log)
81*b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
82*b9c1b51eSKate Stone                 m_class_name.c_str());
832bdbfd50SJim Ingham 
842bdbfd50SJim Ingham   bool should_stop = true;
85*b9c1b51eSKate Stone   if (m_implementation_sp) {
86*b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
87*b9c1b51eSKate Stone                                            ->GetTarget()
88*b9c1b51eSKate Stone                                            .GetDebugger()
89*b9c1b51eSKate Stone                                            .GetCommandInterpreter()
90*b9c1b51eSKate Stone                                            .GetScriptInterpreter();
91*b9c1b51eSKate Stone     if (script_interp) {
922bdbfd50SJim Ingham       bool script_error;
93*b9c1b51eSKate Stone       should_stop = script_interp->ScriptedThreadPlanShouldStop(
94*b9c1b51eSKate Stone           m_implementation_sp, event_ptr, script_error);
952bdbfd50SJim Ingham       if (script_error)
962bdbfd50SJim Ingham         SetPlanComplete(false);
972bdbfd50SJim Ingham     }
982bdbfd50SJim Ingham   }
992bdbfd50SJim Ingham   return should_stop;
1002bdbfd50SJim Ingham }
1012bdbfd50SJim Ingham 
102*b9c1b51eSKate Stone bool ThreadPlanPython::IsPlanStale() {
103c915a7d2SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
104c915a7d2SJim Ingham   if (log)
105*b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
106*b9c1b51eSKate Stone                 m_class_name.c_str());
107c915a7d2SJim Ingham 
108c915a7d2SJim Ingham   bool is_stale = true;
109*b9c1b51eSKate Stone   if (m_implementation_sp) {
110*b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
111*b9c1b51eSKate Stone                                            ->GetTarget()
112*b9c1b51eSKate Stone                                            .GetDebugger()
113*b9c1b51eSKate Stone                                            .GetCommandInterpreter()
114*b9c1b51eSKate Stone                                            .GetScriptInterpreter();
115*b9c1b51eSKate Stone     if (script_interp) {
116c915a7d2SJim Ingham       bool script_error;
117*b9c1b51eSKate Stone       is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
118*b9c1b51eSKate Stone                                                           script_error);
119c915a7d2SJim Ingham       if (script_error)
120c915a7d2SJim Ingham         SetPlanComplete(false);
121c915a7d2SJim Ingham     }
122c915a7d2SJim Ingham   }
123c915a7d2SJim Ingham   return is_stale;
124c915a7d2SJim Ingham }
125c915a7d2SJim Ingham 
126*b9c1b51eSKate Stone bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
1272bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1282bdbfd50SJim Ingham   if (log)
129*b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
130*b9c1b51eSKate Stone                 m_class_name.c_str());
1312bdbfd50SJim Ingham 
1322bdbfd50SJim Ingham   bool explains_stop = true;
133*b9c1b51eSKate Stone   if (m_implementation_sp) {
134*b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
135*b9c1b51eSKate Stone                                            ->GetTarget()
136*b9c1b51eSKate Stone                                            .GetDebugger()
137*b9c1b51eSKate Stone                                            .GetCommandInterpreter()
138*b9c1b51eSKate Stone                                            .GetScriptInterpreter();
139*b9c1b51eSKate Stone     if (script_interp) {
1402bdbfd50SJim Ingham       bool script_error;
141*b9c1b51eSKate Stone       explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
142*b9c1b51eSKate Stone           m_implementation_sp, event_ptr, script_error);
1432bdbfd50SJim Ingham       if (script_error)
1442bdbfd50SJim Ingham         SetPlanComplete(false);
1452bdbfd50SJim Ingham     }
1462bdbfd50SJim Ingham   }
1472bdbfd50SJim Ingham   return explains_stop;
1482bdbfd50SJim Ingham }
1492bdbfd50SJim Ingham 
150*b9c1b51eSKate Stone bool ThreadPlanPython::MischiefManaged() {
1512bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1522bdbfd50SJim Ingham   if (log)
153*b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
154*b9c1b51eSKate Stone                 m_class_name.c_str());
1552bdbfd50SJim Ingham   bool mischief_managed = true;
156*b9c1b51eSKate Stone   if (m_implementation_sp) {
157*b9c1b51eSKate Stone     // I don't really need mischief_managed, since it's simpler to just call
158*b9c1b51eSKate Stone     // SetPlanComplete in should_stop.
1592bdbfd50SJim Ingham     mischief_managed = IsPlanComplete();
1602bdbfd50SJim Ingham     if (mischief_managed)
1612bdbfd50SJim Ingham       m_implementation_sp.reset();
1622bdbfd50SJim Ingham   }
1632bdbfd50SJim Ingham   return mischief_managed;
1642bdbfd50SJim Ingham }
1652bdbfd50SJim Ingham 
166*b9c1b51eSKate Stone lldb::StateType ThreadPlanPython::GetPlanRunState() {
1672bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1682bdbfd50SJim Ingham   if (log)
169*b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
1702bdbfd50SJim Ingham                 m_class_name.c_str());
1712bdbfd50SJim Ingham   lldb::StateType run_state = eStateRunning;
172*b9c1b51eSKate Stone   if (m_implementation_sp) {
173*b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
174*b9c1b51eSKate Stone                                            ->GetTarget()
175*b9c1b51eSKate Stone                                            .GetDebugger()
176*b9c1b51eSKate Stone                                            .GetCommandInterpreter()
177*b9c1b51eSKate Stone                                            .GetScriptInterpreter();
178*b9c1b51eSKate Stone     if (script_interp) {
1792bdbfd50SJim Ingham       bool script_error;
180*b9c1b51eSKate Stone       run_state = script_interp->ScriptedThreadPlanGetRunState(
181*b9c1b51eSKate Stone           m_implementation_sp, script_error);
1822bdbfd50SJim Ingham     }
1832bdbfd50SJim Ingham   }
1842bdbfd50SJim Ingham   return run_state;
1852bdbfd50SJim Ingham }
1862bdbfd50SJim Ingham 
1872bdbfd50SJim Ingham // The ones below are not currently exported to Python.
1882bdbfd50SJim Ingham 
189*b9c1b51eSKate Stone bool ThreadPlanPython::StopOthers() {
190*b9c1b51eSKate Stone   // For now Python plans run all threads, but we should add some controls for
191*b9c1b51eSKate Stone   // this.
1922bdbfd50SJim Ingham   return false;
1932bdbfd50SJim Ingham }
1942bdbfd50SJim Ingham 
195*b9c1b51eSKate Stone void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
196*b9c1b51eSKate Stone   s->Printf("Python thread plan implemented by class %s.",
197*b9c1b51eSKate Stone             m_class_name.c_str());
1982bdbfd50SJim Ingham }
1992bdbfd50SJim Ingham 
200*b9c1b51eSKate Stone bool ThreadPlanPython::WillStop() {
2012bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
2022bdbfd50SJim Ingham   if (log)
203*b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
204*b9c1b51eSKate Stone                 m_class_name.c_str());
2052bdbfd50SJim Ingham   return true;
2062bdbfd50SJim Ingham }
207