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