17aa51b79SEd Maste //===-- ThreadPlan.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/lldb-python.h"
117aa51b79SEd Maste 
127aa51b79SEd Maste #include "lldb/Target/ThreadPlan.h"
137aa51b79SEd Maste 
147aa51b79SEd Maste // C Includes
157aa51b79SEd Maste // C++ Includes
167aa51b79SEd Maste // Other libraries and framework includes
177aa51b79SEd Maste // Project includes
187aa51b79SEd Maste #include "lldb/Core/Debugger.h"
197aa51b79SEd Maste #include "lldb/Core/Log.h"
207aa51b79SEd Maste #include "lldb/Core/State.h"
217aa51b79SEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
227aa51b79SEd Maste #include "lldb/Interpreter/ScriptInterpreter.h"
237aa51b79SEd Maste #include "lldb/Interpreter/ScriptInterpreterPython.h"
247aa51b79SEd Maste #include "lldb/Target/RegisterContext.h"
257aa51b79SEd Maste #include "lldb/Target/Thread.h"
267aa51b79SEd Maste #include "lldb/Target/ThreadPlan.h"
277aa51b79SEd Maste #include "lldb/Target/ThreadPlanPython.h"
287aa51b79SEd Maste #include "lldb/Target/Process.h"
297aa51b79SEd Maste #include "lldb/Target/Target.h"
307aa51b79SEd Maste 
317aa51b79SEd Maste using namespace lldb;
327aa51b79SEd Maste using namespace lldb_private;
337aa51b79SEd Maste 
347aa51b79SEd Maste //----------------------------------------------------------------------
357aa51b79SEd Maste // ThreadPlanPython
367aa51b79SEd Maste //----------------------------------------------------------------------
377aa51b79SEd Maste 
387aa51b79SEd Maste ThreadPlanPython::ThreadPlanPython (Thread &thread, const char *class_name) :
397aa51b79SEd Maste     ThreadPlan (ThreadPlan::eKindPython,
407aa51b79SEd Maste                 "Python based Thread Plan",
417aa51b79SEd Maste                 thread,
427aa51b79SEd Maste                 eVoteNoOpinion,
437aa51b79SEd Maste                 eVoteNoOpinion),
447aa51b79SEd Maste     m_class_name (class_name)
457aa51b79SEd Maste {
467aa51b79SEd Maste     SetIsMasterPlan (true);
477aa51b79SEd Maste     SetOkayToDiscard (true);
487aa51b79SEd Maste     SetPrivate (false);
497aa51b79SEd Maste }
507aa51b79SEd Maste 
517aa51b79SEd Maste ThreadPlanPython::~ThreadPlanPython ()
527aa51b79SEd Maste {
537aa51b79SEd Maste     // FIXME, do I need to decrement the ref count on this implementation object to make it go away?
547aa51b79SEd Maste }
557aa51b79SEd Maste 
567aa51b79SEd Maste bool
577aa51b79SEd Maste ThreadPlanPython::ValidatePlan (Stream *error)
587aa51b79SEd Maste {
597aa51b79SEd Maste     // I have to postpone setting up the implementation till after the constructor because I need to call
607aa51b79SEd Maste     // shared_from_this, which you can't do in the constructor.  So I'll do it here.
617aa51b79SEd Maste     if (m_implementation_sp)
627aa51b79SEd Maste         return true;
637aa51b79SEd Maste     else
647aa51b79SEd Maste         return false;
657aa51b79SEd Maste }
667aa51b79SEd Maste 
677aa51b79SEd Maste void
687aa51b79SEd Maste ThreadPlanPython::DidPush()
697aa51b79SEd Maste {
707aa51b79SEd Maste     // We set up the script side in DidPush, so that it can push other plans in the constructor,
717aa51b79SEd Maste     // and doesn't have to care about the details of DidPush.
727aa51b79SEd Maste 
737aa51b79SEd Maste     if (!m_class_name.empty())
747aa51b79SEd Maste     {
757aa51b79SEd Maste         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
767aa51b79SEd Maste         if (script_interp)
777aa51b79SEd Maste         {
787aa51b79SEd Maste             m_implementation_sp = script_interp->CreateScriptedThreadPlan (m_class_name.c_str(), this->shared_from_this());
797aa51b79SEd Maste         }
807aa51b79SEd Maste     }
817aa51b79SEd Maste }
827aa51b79SEd Maste 
837aa51b79SEd Maste bool
847aa51b79SEd Maste ThreadPlanPython::ShouldStop (Event *event_ptr)
857aa51b79SEd Maste {
867aa51b79SEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
877aa51b79SEd Maste     if (log)
887aa51b79SEd Maste         log->Printf ("%s called on Python Thread Plan: %s )",
897aa51b79SEd Maste                     __PRETTY_FUNCTION__, m_class_name.c_str());
907aa51b79SEd Maste 
917aa51b79SEd Maste     bool should_stop = true;
927aa51b79SEd Maste     if (m_implementation_sp)
937aa51b79SEd Maste     {
947aa51b79SEd Maste         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
957aa51b79SEd Maste         if (script_interp)
967aa51b79SEd Maste         {
977aa51b79SEd Maste             bool script_error;
987aa51b79SEd Maste             should_stop = script_interp->ScriptedThreadPlanShouldStop (m_implementation_sp, event_ptr, script_error);
997aa51b79SEd Maste             if (script_error)
1007aa51b79SEd Maste                 SetPlanComplete(false);
1017aa51b79SEd Maste         }
1027aa51b79SEd Maste     }
1037aa51b79SEd Maste     return should_stop;
1047aa51b79SEd Maste }
1057aa51b79SEd Maste 
1067aa51b79SEd Maste bool
1077aa51b79SEd Maste ThreadPlanPython::DoPlanExplainsStop (Event *event_ptr)
1087aa51b79SEd Maste {
1097aa51b79SEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1107aa51b79SEd Maste     if (log)
1117aa51b79SEd Maste         log->Printf ("%s called on Python Thread Plan: %s )",
1127aa51b79SEd Maste                     __PRETTY_FUNCTION__, m_class_name.c_str());
1137aa51b79SEd Maste 
1147aa51b79SEd Maste     bool explains_stop = true;
1157aa51b79SEd Maste     if (m_implementation_sp)
1167aa51b79SEd Maste     {
1177aa51b79SEd Maste         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1187aa51b79SEd Maste         if (script_interp)
1197aa51b79SEd Maste         {
1207aa51b79SEd Maste             bool script_error;
1217aa51b79SEd Maste             explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error);
1227aa51b79SEd Maste             if (script_error)
1237aa51b79SEd Maste                 SetPlanComplete(false);
1247aa51b79SEd Maste         }
1257aa51b79SEd Maste     }
1267aa51b79SEd Maste     return explains_stop;
1277aa51b79SEd Maste }
1287aa51b79SEd Maste 
1297aa51b79SEd Maste bool
1307aa51b79SEd Maste ThreadPlanPython::MischiefManaged ()
1317aa51b79SEd Maste {
1327aa51b79SEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1337aa51b79SEd Maste     if (log)
1347aa51b79SEd Maste         log->Printf ("%s called on Python Thread Plan: %s )",
1357aa51b79SEd Maste                     __PRETTY_FUNCTION__, m_class_name.c_str());
1367aa51b79SEd Maste     bool mischief_managed = true;
1377aa51b79SEd Maste     if (m_implementation_sp)
1387aa51b79SEd Maste     {
1397aa51b79SEd Maste         // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop.
1407aa51b79SEd Maste         mischief_managed = IsPlanComplete();
1417aa51b79SEd Maste         if (mischief_managed)
1427aa51b79SEd Maste             m_implementation_sp.reset();
1437aa51b79SEd Maste     }
1447aa51b79SEd Maste     return mischief_managed;
1457aa51b79SEd Maste }
1467aa51b79SEd Maste 
1477aa51b79SEd Maste lldb::StateType
1487aa51b79SEd Maste ThreadPlanPython::GetPlanRunState ()
1497aa51b79SEd Maste {
1507aa51b79SEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1517aa51b79SEd Maste     if (log)
1527aa51b79SEd Maste         log->Printf ("%s called on Python Thread Plan: %s )",
1537aa51b79SEd Maste                      __PRETTY_FUNCTION__,
1547aa51b79SEd Maste                      m_class_name.c_str());
1557aa51b79SEd Maste     lldb::StateType run_state = eStateRunning;
1567aa51b79SEd Maste     if (m_implementation_sp)
1577aa51b79SEd Maste     {
1587aa51b79SEd Maste         ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1597aa51b79SEd Maste         if (script_interp)
1607aa51b79SEd Maste         {
1617aa51b79SEd Maste             bool script_error;
1627aa51b79SEd Maste             run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error);
1637aa51b79SEd Maste         }
1647aa51b79SEd Maste     }
1657aa51b79SEd Maste     return run_state;
1667aa51b79SEd Maste }
1677aa51b79SEd Maste 
1687aa51b79SEd Maste // The ones below are not currently exported to Python.
1697aa51b79SEd Maste 
1707aa51b79SEd Maste bool
1717aa51b79SEd Maste ThreadPlanPython::StopOthers ()
1727aa51b79SEd Maste {
1737aa51b79SEd Maste     // For now Python plans run all threads, but we should add some controls for this.
1747aa51b79SEd Maste     return false;
1757aa51b79SEd Maste }
1767aa51b79SEd Maste 
1777aa51b79SEd Maste void
1787aa51b79SEd Maste ThreadPlanPython::GetDescription (Stream *s,
1797aa51b79SEd Maste                                 lldb::DescriptionLevel level)
1807aa51b79SEd Maste {
1817aa51b79SEd Maste     s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str());
1827aa51b79SEd Maste }
1837aa51b79SEd Maste 
1847aa51b79SEd Maste bool
1857aa51b79SEd Maste ThreadPlanPython::WillStop ()
1867aa51b79SEd Maste {
1877aa51b79SEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
1887aa51b79SEd Maste     if (log)
1897aa51b79SEd Maste         log->Printf ("%s called on Python Thread Plan: %s )",
1907aa51b79SEd Maste                     __PRETTY_FUNCTION__, m_class_name.c_str());
1917aa51b79SEd Maste     return true;
1927aa51b79SEd Maste }
193