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" 212bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h" 222bdbfd50SJim Ingham #include "lldb/Target/Thread.h" 232bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h" 242bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h" 252bdbfd50SJim Ingham #include "lldb/Target/Process.h" 262bdbfd50SJim Ingham #include "lldb/Target/Target.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 352bdbfd50SJim Ingham ThreadPlanPython::ThreadPlanPython (Thread &thread, const char *class_name) : 362bdbfd50SJim Ingham ThreadPlan (ThreadPlan::eKindPython, 372bdbfd50SJim Ingham "Python based Thread Plan", 382bdbfd50SJim Ingham thread, 392bdbfd50SJim Ingham eVoteNoOpinion, 402bdbfd50SJim Ingham eVoteNoOpinion), 412bdbfd50SJim Ingham m_class_name (class_name) 422bdbfd50SJim Ingham { 432bdbfd50SJim Ingham SetIsMasterPlan (true); 442bdbfd50SJim Ingham SetOkayToDiscard (true); 452bdbfd50SJim Ingham SetPrivate (false); 462bdbfd50SJim Ingham } 472bdbfd50SJim Ingham 482bdbfd50SJim Ingham ThreadPlanPython::~ThreadPlanPython () 492bdbfd50SJim Ingham { 502bdbfd50SJim Ingham // FIXME, do I need to decrement the ref count on this implementation object to make it go away? 512bdbfd50SJim Ingham } 522bdbfd50SJim Ingham 532bdbfd50SJim Ingham bool 542bdbfd50SJim Ingham ThreadPlanPython::ValidatePlan (Stream *error) 552bdbfd50SJim Ingham { 562bdbfd50SJim Ingham // I have to postpone setting up the implementation till after the constructor because I need to call 572bdbfd50SJim Ingham // shared_from_this, which you can't do in the constructor. So I'll do it here. 582bdbfd50SJim Ingham if (m_implementation_sp) 592bdbfd50SJim Ingham return true; 602bdbfd50SJim Ingham else 612bdbfd50SJim Ingham return false; 622bdbfd50SJim Ingham } 632bdbfd50SJim Ingham 642bdbfd50SJim Ingham void 652bdbfd50SJim Ingham ThreadPlanPython::DidPush() 662bdbfd50SJim Ingham { 672bdbfd50SJim Ingham // We set up the script side in DidPush, so that it can push other plans in the constructor, 682bdbfd50SJim Ingham // and doesn't have to care about the details of DidPush. 692bdbfd50SJim Ingham 702bdbfd50SJim Ingham if (!m_class_name.empty()) 712bdbfd50SJim Ingham { 722bdbfd50SJim Ingham ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 732bdbfd50SJim Ingham if (script_interp) 742bdbfd50SJim Ingham { 752bdbfd50SJim Ingham m_implementation_sp = script_interp->CreateScriptedThreadPlan (m_class_name.c_str(), this->shared_from_this()); 762bdbfd50SJim Ingham } 772bdbfd50SJim Ingham } 782bdbfd50SJim Ingham } 792bdbfd50SJim Ingham 802bdbfd50SJim Ingham bool 812bdbfd50SJim Ingham ThreadPlanPython::ShouldStop (Event *event_ptr) 822bdbfd50SJim Ingham { 832bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 842bdbfd50SJim Ingham if (log) 852bdbfd50SJim Ingham log->Printf ("%s called on Python Thread Plan: %s )", 862bdbfd50SJim Ingham __PRETTY_FUNCTION__, m_class_name.c_str()); 872bdbfd50SJim Ingham 882bdbfd50SJim Ingham bool should_stop = true; 892bdbfd50SJim Ingham if (m_implementation_sp) 902bdbfd50SJim Ingham { 912bdbfd50SJim Ingham ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 922bdbfd50SJim Ingham if (script_interp) 932bdbfd50SJim Ingham { 942bdbfd50SJim Ingham bool script_error; 952bdbfd50SJim Ingham should_stop = script_interp->ScriptedThreadPlanShouldStop (m_implementation_sp, event_ptr, script_error); 962bdbfd50SJim Ingham if (script_error) 972bdbfd50SJim Ingham SetPlanComplete(false); 982bdbfd50SJim Ingham } 992bdbfd50SJim Ingham } 1002bdbfd50SJim Ingham return should_stop; 1012bdbfd50SJim Ingham } 1022bdbfd50SJim Ingham 1032bdbfd50SJim Ingham bool 104*c915a7d2SJim Ingham ThreadPlanPython::IsPlanStale() 105*c915a7d2SJim Ingham { 106*c915a7d2SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 107*c915a7d2SJim Ingham if (log) 108*c915a7d2SJim Ingham log->Printf ("%s called on Python Thread Plan: %s )", 109*c915a7d2SJim Ingham __PRETTY_FUNCTION__, m_class_name.c_str()); 110*c915a7d2SJim Ingham 111*c915a7d2SJim Ingham bool is_stale = true; 112*c915a7d2SJim Ingham if (m_implementation_sp) 113*c915a7d2SJim Ingham { 114*c915a7d2SJim Ingham ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 115*c915a7d2SJim Ingham if (script_interp) 116*c915a7d2SJim Ingham { 117*c915a7d2SJim Ingham bool script_error; 118*c915a7d2SJim Ingham is_stale = script_interp->ScriptedThreadPlanIsStale (m_implementation_sp, script_error); 119*c915a7d2SJim Ingham if (script_error) 120*c915a7d2SJim Ingham SetPlanComplete(false); 121*c915a7d2SJim Ingham } 122*c915a7d2SJim Ingham } 123*c915a7d2SJim Ingham return is_stale; 124*c915a7d2SJim Ingham } 125*c915a7d2SJim Ingham 126*c915a7d2SJim Ingham bool 1272bdbfd50SJim Ingham ThreadPlanPython::DoPlanExplainsStop (Event *event_ptr) 1282bdbfd50SJim Ingham { 1292bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 1302bdbfd50SJim Ingham if (log) 1312bdbfd50SJim Ingham log->Printf ("%s called on Python Thread Plan: %s )", 1322bdbfd50SJim Ingham __PRETTY_FUNCTION__, m_class_name.c_str()); 1332bdbfd50SJim Ingham 1342bdbfd50SJim Ingham bool explains_stop = true; 1352bdbfd50SJim Ingham if (m_implementation_sp) 1362bdbfd50SJim Ingham { 1372bdbfd50SJim Ingham ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 1382bdbfd50SJim Ingham if (script_interp) 1392bdbfd50SJim Ingham { 1402bdbfd50SJim Ingham bool script_error; 1412bdbfd50SJim Ingham explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error); 1422bdbfd50SJim Ingham if (script_error) 1432bdbfd50SJim Ingham SetPlanComplete(false); 1442bdbfd50SJim Ingham } 1452bdbfd50SJim Ingham } 1462bdbfd50SJim Ingham return explains_stop; 1472bdbfd50SJim Ingham } 1482bdbfd50SJim Ingham 1492bdbfd50SJim Ingham bool 1502bdbfd50SJim Ingham ThreadPlanPython::MischiefManaged () 1512bdbfd50SJim Ingham { 1522bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 1532bdbfd50SJim Ingham if (log) 1542bdbfd50SJim Ingham log->Printf ("%s called on Python Thread Plan: %s )", 1552bdbfd50SJim Ingham __PRETTY_FUNCTION__, m_class_name.c_str()); 1562bdbfd50SJim Ingham bool mischief_managed = true; 1572bdbfd50SJim Ingham if (m_implementation_sp) 1582bdbfd50SJim Ingham { 1592bdbfd50SJim Ingham // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop. 1602bdbfd50SJim Ingham mischief_managed = IsPlanComplete(); 1612bdbfd50SJim Ingham if (mischief_managed) 1622bdbfd50SJim Ingham m_implementation_sp.reset(); 1632bdbfd50SJim Ingham } 1642bdbfd50SJim Ingham return mischief_managed; 1652bdbfd50SJim Ingham } 1662bdbfd50SJim Ingham 1672bdbfd50SJim Ingham lldb::StateType 1682bdbfd50SJim Ingham ThreadPlanPython::GetPlanRunState () 1692bdbfd50SJim Ingham { 1702bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 1712bdbfd50SJim Ingham if (log) 1722bdbfd50SJim Ingham log->Printf ("%s called on Python Thread Plan: %s )", 1732bdbfd50SJim Ingham __PRETTY_FUNCTION__, 1742bdbfd50SJim Ingham m_class_name.c_str()); 1752bdbfd50SJim Ingham lldb::StateType run_state = eStateRunning; 1762bdbfd50SJim Ingham if (m_implementation_sp) 1772bdbfd50SJim Ingham { 1782bdbfd50SJim Ingham ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 1792bdbfd50SJim Ingham if (script_interp) 1802bdbfd50SJim Ingham { 1812bdbfd50SJim Ingham bool script_error; 1822bdbfd50SJim Ingham run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error); 1832bdbfd50SJim Ingham } 1842bdbfd50SJim Ingham } 1852bdbfd50SJim Ingham return run_state; 1862bdbfd50SJim Ingham } 1872bdbfd50SJim Ingham 1882bdbfd50SJim Ingham // The ones below are not currently exported to Python. 1892bdbfd50SJim Ingham 1902bdbfd50SJim Ingham bool 1912bdbfd50SJim Ingham ThreadPlanPython::StopOthers () 1922bdbfd50SJim Ingham { 1932bdbfd50SJim Ingham // For now Python plans run all threads, but we should add some controls for this. 1942bdbfd50SJim Ingham return false; 1952bdbfd50SJim Ingham } 1962bdbfd50SJim Ingham 1972bdbfd50SJim Ingham void 1982bdbfd50SJim Ingham ThreadPlanPython::GetDescription (Stream *s, 1992bdbfd50SJim Ingham lldb::DescriptionLevel level) 2002bdbfd50SJim Ingham { 2012bdbfd50SJim Ingham s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str()); 2022bdbfd50SJim Ingham } 2032bdbfd50SJim Ingham 2042bdbfd50SJim Ingham bool 2052bdbfd50SJim Ingham ThreadPlanPython::WillStop () 2062bdbfd50SJim Ingham { 2072bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 2082bdbfd50SJim Ingham if (log) 2092bdbfd50SJim Ingham log->Printf ("%s called on Python Thread Plan: %s )", 2102bdbfd50SJim Ingham __PRETTY_FUNCTION__, m_class_name.c_str()); 2112bdbfd50SJim Ingham return true; 2122bdbfd50SJim Ingham } 213