1696bd635SAlexander Shaposhnikov //===-- ThreadPlanPython.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/State.h" 182bdbfd50SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 192bdbfd50SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h" 20b9c1b51eSKate Stone #include "lldb/Target/Process.h" 212bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h" 22b9c1b51eSKate Stone #include "lldb/Target/Target.h" 232bdbfd50SJim Ingham #include "lldb/Target/Thread.h" 242bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h" 252bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h" 266f9e6901SZachary Turner #include "lldb/Utility/Log.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 35b9c1b51eSKate Stone ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name) 36b9c1b51eSKate Stone : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread, 37b9c1b51eSKate Stone eVoteNoOpinion, eVoteNoOpinion), 38b9c1b51eSKate Stone m_class_name(class_name) { 392bdbfd50SJim Ingham SetIsMasterPlan(true); 402bdbfd50SJim Ingham SetOkayToDiscard(true); 412bdbfd50SJim Ingham SetPrivate(false); 422bdbfd50SJim Ingham } 432bdbfd50SJim Ingham 44b9c1b51eSKate Stone ThreadPlanPython::~ThreadPlanPython() { 45b9c1b51eSKate Stone // FIXME, do I need to decrement the ref count on this implementation object 46b9c1b51eSKate Stone // to make it go away? 472bdbfd50SJim Ingham } 482bdbfd50SJim Ingham 49b9c1b51eSKate Stone bool ThreadPlanPython::ValidatePlan(Stream *error) { 50b9c1b51eSKate Stone // I have to postpone setting up the implementation till after the constructor 51b9c1b51eSKate Stone // because I need to call 52b9c1b51eSKate Stone // shared_from_this, which you can't do in the constructor. So I'll do it 53b9c1b51eSKate Stone // here. 542bdbfd50SJim Ingham if (m_implementation_sp) 552bdbfd50SJim Ingham return true; 562bdbfd50SJim Ingham else 572bdbfd50SJim Ingham return false; 582bdbfd50SJim Ingham } 592bdbfd50SJim Ingham 60b9c1b51eSKate Stone void ThreadPlanPython::DidPush() { 61b9c1b51eSKate Stone // We set up the script side in DidPush, so that it can push other plans in 62*05097246SAdrian Prantl // the constructor, and doesn't have to care about the details of DidPush. 632bdbfd50SJim Ingham 64b9c1b51eSKate Stone if (!m_class_name.empty()) { 65b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 66b9c1b51eSKate Stone ->GetTarget() 67b9c1b51eSKate Stone .GetDebugger() 68b9c1b51eSKate Stone .GetCommandInterpreter() 69b9c1b51eSKate Stone .GetScriptInterpreter(); 70b9c1b51eSKate Stone if (script_interp) { 71b9c1b51eSKate Stone m_implementation_sp = script_interp->CreateScriptedThreadPlan( 72b9c1b51eSKate Stone m_class_name.c_str(), this->shared_from_this()); 732bdbfd50SJim Ingham } 742bdbfd50SJim Ingham } 752bdbfd50SJim Ingham } 762bdbfd50SJim Ingham 77b9c1b51eSKate Stone bool ThreadPlanPython::ShouldStop(Event *event_ptr) { 782bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 792bdbfd50SJim Ingham if (log) 80b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 81b9c1b51eSKate Stone m_class_name.c_str()); 822bdbfd50SJim Ingham 832bdbfd50SJim Ingham bool should_stop = true; 84b9c1b51eSKate Stone if (m_implementation_sp) { 85b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 86b9c1b51eSKate Stone ->GetTarget() 87b9c1b51eSKate Stone .GetDebugger() 88b9c1b51eSKate Stone .GetCommandInterpreter() 89b9c1b51eSKate Stone .GetScriptInterpreter(); 90b9c1b51eSKate Stone if (script_interp) { 912bdbfd50SJim Ingham bool script_error; 92b9c1b51eSKate Stone should_stop = script_interp->ScriptedThreadPlanShouldStop( 93b9c1b51eSKate Stone m_implementation_sp, event_ptr, script_error); 942bdbfd50SJim Ingham if (script_error) 952bdbfd50SJim Ingham SetPlanComplete(false); 962bdbfd50SJim Ingham } 972bdbfd50SJim Ingham } 982bdbfd50SJim Ingham return should_stop; 992bdbfd50SJim Ingham } 1002bdbfd50SJim Ingham 101b9c1b51eSKate Stone bool ThreadPlanPython::IsPlanStale() { 102c915a7d2SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 103c915a7d2SJim Ingham if (log) 104b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 105b9c1b51eSKate Stone m_class_name.c_str()); 106c915a7d2SJim Ingham 107c915a7d2SJim Ingham bool is_stale = true; 108b9c1b51eSKate Stone if (m_implementation_sp) { 109b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 110b9c1b51eSKate Stone ->GetTarget() 111b9c1b51eSKate Stone .GetDebugger() 112b9c1b51eSKate Stone .GetCommandInterpreter() 113b9c1b51eSKate Stone .GetScriptInterpreter(); 114b9c1b51eSKate Stone if (script_interp) { 115c915a7d2SJim Ingham bool script_error; 116b9c1b51eSKate Stone is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp, 117b9c1b51eSKate Stone script_error); 118c915a7d2SJim Ingham if (script_error) 119c915a7d2SJim Ingham SetPlanComplete(false); 120c915a7d2SJim Ingham } 121c915a7d2SJim Ingham } 122c915a7d2SJim Ingham return is_stale; 123c915a7d2SJim Ingham } 124c915a7d2SJim Ingham 125b9c1b51eSKate Stone bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { 1262bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1272bdbfd50SJim Ingham if (log) 128b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 129b9c1b51eSKate Stone m_class_name.c_str()); 1302bdbfd50SJim Ingham 1312bdbfd50SJim Ingham bool explains_stop = true; 132b9c1b51eSKate Stone if (m_implementation_sp) { 133b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 134b9c1b51eSKate Stone ->GetTarget() 135b9c1b51eSKate Stone .GetDebugger() 136b9c1b51eSKate Stone .GetCommandInterpreter() 137b9c1b51eSKate Stone .GetScriptInterpreter(); 138b9c1b51eSKate Stone if (script_interp) { 1392bdbfd50SJim Ingham bool script_error; 140b9c1b51eSKate Stone explains_stop = script_interp->ScriptedThreadPlanExplainsStop( 141b9c1b51eSKate Stone 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 149b9c1b51eSKate Stone bool ThreadPlanPython::MischiefManaged() { 1502bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1512bdbfd50SJim Ingham if (log) 152b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 153b9c1b51eSKate Stone m_class_name.c_str()); 1542bdbfd50SJim Ingham bool mischief_managed = true; 155b9c1b51eSKate Stone if (m_implementation_sp) { 156b9c1b51eSKate Stone // I don't really need mischief_managed, since it's simpler to just call 157b9c1b51eSKate Stone // SetPlanComplete in should_stop. 1582bdbfd50SJim Ingham mischief_managed = IsPlanComplete(); 1592bdbfd50SJim Ingham if (mischief_managed) 1602bdbfd50SJim Ingham m_implementation_sp.reset(); 1612bdbfd50SJim Ingham } 1622bdbfd50SJim Ingham return mischief_managed; 1632bdbfd50SJim Ingham } 1642bdbfd50SJim Ingham 165b9c1b51eSKate Stone lldb::StateType ThreadPlanPython::GetPlanRunState() { 1662bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1672bdbfd50SJim Ingham if (log) 168b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 1692bdbfd50SJim Ingham m_class_name.c_str()); 1702bdbfd50SJim Ingham lldb::StateType run_state = eStateRunning; 171b9c1b51eSKate Stone if (m_implementation_sp) { 172b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 173b9c1b51eSKate Stone ->GetTarget() 174b9c1b51eSKate Stone .GetDebugger() 175b9c1b51eSKate Stone .GetCommandInterpreter() 176b9c1b51eSKate Stone .GetScriptInterpreter(); 177b9c1b51eSKate Stone if (script_interp) { 1782bdbfd50SJim Ingham bool script_error; 179b9c1b51eSKate Stone run_state = script_interp->ScriptedThreadPlanGetRunState( 180b9c1b51eSKate Stone m_implementation_sp, script_error); 1812bdbfd50SJim Ingham } 1822bdbfd50SJim Ingham } 1832bdbfd50SJim Ingham return run_state; 1842bdbfd50SJim Ingham } 1852bdbfd50SJim Ingham 1862bdbfd50SJim Ingham // The ones below are not currently exported to Python. 1872bdbfd50SJim Ingham 188b9c1b51eSKate Stone bool ThreadPlanPython::StopOthers() { 189b9c1b51eSKate Stone // For now Python plans run all threads, but we should add some controls for 190b9c1b51eSKate Stone // this. 1912bdbfd50SJim Ingham return false; 1922bdbfd50SJim Ingham } 1932bdbfd50SJim Ingham 194b9c1b51eSKate Stone void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { 195b9c1b51eSKate Stone s->Printf("Python thread plan implemented by class %s.", 196b9c1b51eSKate Stone m_class_name.c_str()); 1972bdbfd50SJim Ingham } 1982bdbfd50SJim Ingham 199b9c1b51eSKate Stone bool ThreadPlanPython::WillStop() { 2002bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 2012bdbfd50SJim Ingham if (log) 202b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 203b9c1b51eSKate Stone m_class_name.c_str()); 2042bdbfd50SJim Ingham return true; 2052bdbfd50SJim Ingham } 206