1435933ddSDimitry Andric //===-- ThreadPlanPython.cpp ------------------------------------*- C++ -*-===//
27aa51b79SEd Maste //
37aa51b79SEd Maste //                     The LLVM Compiler Infrastructure
47aa51b79SEd Maste //
57aa51b79SEd Maste // This file is distributed under the University of Illinois Open Source
67aa51b79SEd Maste // License. See LICENSE.TXT for details.
77aa51b79SEd Maste //
87aa51b79SEd Maste //===----------------------------------------------------------------------===//
97aa51b79SEd Maste 
107aa51b79SEd Maste #include "lldb/Target/ThreadPlan.h"
117aa51b79SEd Maste 
127aa51b79SEd Maste #include "lldb/Core/Debugger.h"
137aa51b79SEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
147aa51b79SEd Maste #include "lldb/Interpreter/ScriptInterpreter.h"
15435933ddSDimitry Andric #include "lldb/Target/Process.h"
167aa51b79SEd Maste #include "lldb/Target/RegisterContext.h"
17435933ddSDimitry Andric #include "lldb/Target/Target.h"
187aa51b79SEd Maste #include "lldb/Target/Thread.h"
197aa51b79SEd Maste #include "lldb/Target/ThreadPlan.h"
207aa51b79SEd Maste #include "lldb/Target/ThreadPlanPython.h"
21f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
22*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
237aa51b79SEd Maste 
247aa51b79SEd Maste using namespace lldb;
257aa51b79SEd Maste using namespace lldb_private;
267aa51b79SEd Maste 
277aa51b79SEd Maste //----------------------------------------------------------------------
287aa51b79SEd Maste // ThreadPlanPython
297aa51b79SEd Maste //----------------------------------------------------------------------
307aa51b79SEd Maste 
ThreadPlanPython(Thread & thread,const char * class_name)31435933ddSDimitry Andric ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
32435933ddSDimitry Andric     : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
33435933ddSDimitry Andric                  eVoteNoOpinion, eVoteNoOpinion),
34*b5893f02SDimitry Andric       m_class_name(class_name), m_did_push(false) {
357aa51b79SEd Maste   SetIsMasterPlan(true);
367aa51b79SEd Maste   SetOkayToDiscard(true);
377aa51b79SEd Maste   SetPrivate(false);
387aa51b79SEd Maste }
397aa51b79SEd Maste 
~ThreadPlanPython()40435933ddSDimitry Andric ThreadPlanPython::~ThreadPlanPython() {
41435933ddSDimitry Andric   // FIXME, do I need to decrement the ref count on this implementation object
42435933ddSDimitry Andric   // to make it go away?
437aa51b79SEd Maste }
447aa51b79SEd Maste 
ValidatePlan(Stream * error)45435933ddSDimitry Andric bool ThreadPlanPython::ValidatePlan(Stream *error) {
46*b5893f02SDimitry Andric   if (!m_did_push)
477aa51b79SEd Maste     return true;
48*b5893f02SDimitry Andric 
49*b5893f02SDimitry Andric   if (!m_implementation_sp) {
50*b5893f02SDimitry Andric     if (error)
51*b5893f02SDimitry Andric       error->Printf("Python thread plan does not have an implementation");
527aa51b79SEd Maste     return false;
537aa51b79SEd Maste   }
547aa51b79SEd Maste 
55*b5893f02SDimitry Andric   return true;
56*b5893f02SDimitry Andric }
57*b5893f02SDimitry Andric 
DidPush()58435933ddSDimitry Andric void ThreadPlanPython::DidPush() {
59435933ddSDimitry Andric   // We set up the script side in DidPush, so that it can push other plans in
604ba319b5SDimitry Andric   // the constructor, and doesn't have to care about the details of DidPush.
61*b5893f02SDimitry Andric   m_did_push = true;
62435933ddSDimitry Andric   if (!m_class_name.empty()) {
63435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
64435933ddSDimitry Andric                                            ->GetTarget()
65435933ddSDimitry Andric                                            .GetDebugger()
66435933ddSDimitry Andric                                            .GetCommandInterpreter()
67435933ddSDimitry Andric                                            .GetScriptInterpreter();
68435933ddSDimitry Andric     if (script_interp) {
69435933ddSDimitry Andric       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
70435933ddSDimitry Andric           m_class_name.c_str(), this->shared_from_this());
717aa51b79SEd Maste     }
727aa51b79SEd Maste   }
737aa51b79SEd Maste }
747aa51b79SEd Maste 
ShouldStop(Event * event_ptr)75435933ddSDimitry Andric bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
767aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
777aa51b79SEd Maste   if (log)
78435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
79435933ddSDimitry Andric                 m_class_name.c_str());
807aa51b79SEd Maste 
817aa51b79SEd Maste   bool should_stop = true;
82435933ddSDimitry Andric   if (m_implementation_sp) {
83435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
84435933ddSDimitry Andric                                            ->GetTarget()
85435933ddSDimitry Andric                                            .GetDebugger()
86435933ddSDimitry Andric                                            .GetCommandInterpreter()
87435933ddSDimitry Andric                                            .GetScriptInterpreter();
88435933ddSDimitry Andric     if (script_interp) {
897aa51b79SEd Maste       bool script_error;
90435933ddSDimitry Andric       should_stop = script_interp->ScriptedThreadPlanShouldStop(
91435933ddSDimitry Andric           m_implementation_sp, event_ptr, script_error);
927aa51b79SEd Maste       if (script_error)
937aa51b79SEd Maste         SetPlanComplete(false);
947aa51b79SEd Maste     }
957aa51b79SEd Maste   }
967aa51b79SEd Maste   return should_stop;
977aa51b79SEd Maste }
987aa51b79SEd Maste 
IsPlanStale()99435933ddSDimitry Andric bool ThreadPlanPython::IsPlanStale() {
1007aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1017aa51b79SEd Maste   if (log)
102435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
103435933ddSDimitry Andric                 m_class_name.c_str());
104435933ddSDimitry Andric 
105435933ddSDimitry Andric   bool is_stale = true;
106435933ddSDimitry Andric   if (m_implementation_sp) {
107435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
108435933ddSDimitry Andric                                            ->GetTarget()
109435933ddSDimitry Andric                                            .GetDebugger()
110435933ddSDimitry Andric                                            .GetCommandInterpreter()
111435933ddSDimitry Andric                                            .GetScriptInterpreter();
112435933ddSDimitry Andric     if (script_interp) {
113435933ddSDimitry Andric       bool script_error;
114435933ddSDimitry Andric       is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
115435933ddSDimitry Andric                                                           script_error);
116435933ddSDimitry Andric       if (script_error)
117435933ddSDimitry Andric         SetPlanComplete(false);
118435933ddSDimitry Andric     }
119435933ddSDimitry Andric   }
120435933ddSDimitry Andric   return is_stale;
121435933ddSDimitry Andric }
122435933ddSDimitry Andric 
DoPlanExplainsStop(Event * event_ptr)123435933ddSDimitry Andric bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
124435933ddSDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
125435933ddSDimitry Andric   if (log)
126435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
127435933ddSDimitry Andric                 m_class_name.c_str());
1287aa51b79SEd Maste 
1297aa51b79SEd Maste   bool explains_stop = true;
130435933ddSDimitry Andric   if (m_implementation_sp) {
131435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
132435933ddSDimitry Andric                                            ->GetTarget()
133435933ddSDimitry Andric                                            .GetDebugger()
134435933ddSDimitry Andric                                            .GetCommandInterpreter()
135435933ddSDimitry Andric                                            .GetScriptInterpreter();
136435933ddSDimitry Andric     if (script_interp) {
1377aa51b79SEd Maste       bool script_error;
138435933ddSDimitry Andric       explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
139435933ddSDimitry Andric           m_implementation_sp, event_ptr, script_error);
1407aa51b79SEd Maste       if (script_error)
1417aa51b79SEd Maste         SetPlanComplete(false);
1427aa51b79SEd Maste     }
1437aa51b79SEd Maste   }
1447aa51b79SEd Maste   return explains_stop;
1457aa51b79SEd Maste }
1467aa51b79SEd Maste 
MischiefManaged()147435933ddSDimitry Andric bool ThreadPlanPython::MischiefManaged() {
1487aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1497aa51b79SEd Maste   if (log)
150435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
151435933ddSDimitry Andric                 m_class_name.c_str());
1527aa51b79SEd Maste   bool mischief_managed = true;
153435933ddSDimitry Andric   if (m_implementation_sp) {
154435933ddSDimitry Andric     // I don't really need mischief_managed, since it's simpler to just call
155435933ddSDimitry Andric     // SetPlanComplete in should_stop.
1567aa51b79SEd Maste     mischief_managed = IsPlanComplete();
1577aa51b79SEd Maste     if (mischief_managed)
1587aa51b79SEd Maste       m_implementation_sp.reset();
1597aa51b79SEd Maste   }
1607aa51b79SEd Maste   return mischief_managed;
1617aa51b79SEd Maste }
1627aa51b79SEd Maste 
GetPlanRunState()163435933ddSDimitry Andric lldb::StateType ThreadPlanPython::GetPlanRunState() {
1647aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1657aa51b79SEd Maste   if (log)
166435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
1677aa51b79SEd Maste                 m_class_name.c_str());
1687aa51b79SEd Maste   lldb::StateType run_state = eStateRunning;
169435933ddSDimitry Andric   if (m_implementation_sp) {
170435933ddSDimitry Andric     ScriptInterpreter *script_interp = m_thread.GetProcess()
171435933ddSDimitry Andric                                            ->GetTarget()
172435933ddSDimitry Andric                                            .GetDebugger()
173435933ddSDimitry Andric                                            .GetCommandInterpreter()
174435933ddSDimitry Andric                                            .GetScriptInterpreter();
175435933ddSDimitry Andric     if (script_interp) {
1767aa51b79SEd Maste       bool script_error;
177435933ddSDimitry Andric       run_state = script_interp->ScriptedThreadPlanGetRunState(
178435933ddSDimitry Andric           m_implementation_sp, script_error);
1797aa51b79SEd Maste     }
1807aa51b79SEd Maste   }
1817aa51b79SEd Maste   return run_state;
1827aa51b79SEd Maste }
1837aa51b79SEd Maste 
1847aa51b79SEd Maste // The ones below are not currently exported to Python.
1857aa51b79SEd Maste 
StopOthers()186435933ddSDimitry Andric bool ThreadPlanPython::StopOthers() {
187435933ddSDimitry Andric   // For now Python plans run all threads, but we should add some controls for
188435933ddSDimitry Andric   // this.
1897aa51b79SEd Maste   return false;
1907aa51b79SEd Maste }
1917aa51b79SEd Maste 
GetDescription(Stream * s,lldb::DescriptionLevel level)192435933ddSDimitry Andric void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
193435933ddSDimitry Andric   s->Printf("Python thread plan implemented by class %s.",
194435933ddSDimitry Andric             m_class_name.c_str());
1957aa51b79SEd Maste }
1967aa51b79SEd Maste 
WillStop()197435933ddSDimitry Andric bool ThreadPlanPython::WillStop() {
1987aa51b79SEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1997aa51b79SEd Maste   if (log)
200435933ddSDimitry Andric     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
201435933ddSDimitry Andric                 m_class_name.c_str());
2027aa51b79SEd Maste   return true;
2037aa51b79SEd Maste }
204