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 #include "lldb/Core/Debugger.h" 132bdbfd50SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 142bdbfd50SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h" 15b9c1b51eSKate Stone #include "lldb/Target/Process.h" 162bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h" 17b9c1b51eSKate Stone #include "lldb/Target/Target.h" 182bdbfd50SJim Ingham #include "lldb/Target/Thread.h" 192bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h" 202bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h" 216f9e6901SZachary Turner #include "lldb/Utility/Log.h" 22d821c997SPavel Labath #include "lldb/Utility/State.h" 232bdbfd50SJim Ingham 242bdbfd50SJim Ingham using namespace lldb; 252bdbfd50SJim Ingham using namespace lldb_private; 262bdbfd50SJim Ingham 272bdbfd50SJim Ingham //---------------------------------------------------------------------- 282bdbfd50SJim Ingham // ThreadPlanPython 292bdbfd50SJim Ingham //---------------------------------------------------------------------- 302bdbfd50SJim Ingham 31b9c1b51eSKate Stone ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name) 32b9c1b51eSKate Stone : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread, 33b9c1b51eSKate Stone eVoteNoOpinion, eVoteNoOpinion), 34*e103ae92SJonas Devlieghere m_class_name(class_name), m_did_push(false) { 352bdbfd50SJim Ingham SetIsMasterPlan(true); 362bdbfd50SJim Ingham SetOkayToDiscard(true); 372bdbfd50SJim Ingham SetPrivate(false); 382bdbfd50SJim Ingham } 392bdbfd50SJim Ingham 40b9c1b51eSKate Stone ThreadPlanPython::~ThreadPlanPython() { 41b9c1b51eSKate Stone // FIXME, do I need to decrement the ref count on this implementation object 42b9c1b51eSKate Stone // to make it go away? 432bdbfd50SJim Ingham } 442bdbfd50SJim Ingham 45b9c1b51eSKate Stone bool ThreadPlanPython::ValidatePlan(Stream *error) { 46*e103ae92SJonas Devlieghere if (!m_did_push) 472bdbfd50SJim Ingham return true; 48*e103ae92SJonas Devlieghere 49*e103ae92SJonas Devlieghere if (!m_implementation_sp) { 50*e103ae92SJonas Devlieghere if (error) 51*e103ae92SJonas Devlieghere error->Printf("Python thread plan does not have an implementation"); 522bdbfd50SJim Ingham return false; 532bdbfd50SJim Ingham } 542bdbfd50SJim Ingham 55*e103ae92SJonas Devlieghere return true; 56*e103ae92SJonas Devlieghere } 57*e103ae92SJonas Devlieghere 58b9c1b51eSKate Stone void ThreadPlanPython::DidPush() { 59b9c1b51eSKate Stone // We set up the script side in DidPush, so that it can push other plans in 6005097246SAdrian Prantl // the constructor, and doesn't have to care about the details of DidPush. 61*e103ae92SJonas Devlieghere m_did_push = true; 62b9c1b51eSKate Stone if (!m_class_name.empty()) { 63b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 64b9c1b51eSKate Stone ->GetTarget() 65b9c1b51eSKate Stone .GetDebugger() 66b9c1b51eSKate Stone .GetCommandInterpreter() 67b9c1b51eSKate Stone .GetScriptInterpreter(); 68b9c1b51eSKate Stone if (script_interp) { 69b9c1b51eSKate Stone m_implementation_sp = script_interp->CreateScriptedThreadPlan( 70b9c1b51eSKate Stone m_class_name.c_str(), this->shared_from_this()); 712bdbfd50SJim Ingham } 722bdbfd50SJim Ingham } 732bdbfd50SJim Ingham } 742bdbfd50SJim Ingham 75b9c1b51eSKate Stone bool ThreadPlanPython::ShouldStop(Event *event_ptr) { 762bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 772bdbfd50SJim Ingham if (log) 78b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 79b9c1b51eSKate Stone m_class_name.c_str()); 802bdbfd50SJim Ingham 812bdbfd50SJim Ingham bool should_stop = true; 82b9c1b51eSKate Stone if (m_implementation_sp) { 83b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 84b9c1b51eSKate Stone ->GetTarget() 85b9c1b51eSKate Stone .GetDebugger() 86b9c1b51eSKate Stone .GetCommandInterpreter() 87b9c1b51eSKate Stone .GetScriptInterpreter(); 88b9c1b51eSKate Stone if (script_interp) { 892bdbfd50SJim Ingham bool script_error; 90b9c1b51eSKate Stone should_stop = script_interp->ScriptedThreadPlanShouldStop( 91b9c1b51eSKate Stone m_implementation_sp, event_ptr, script_error); 922bdbfd50SJim Ingham if (script_error) 932bdbfd50SJim Ingham SetPlanComplete(false); 942bdbfd50SJim Ingham } 952bdbfd50SJim Ingham } 962bdbfd50SJim Ingham return should_stop; 972bdbfd50SJim Ingham } 982bdbfd50SJim Ingham 99b9c1b51eSKate Stone bool ThreadPlanPython::IsPlanStale() { 100c915a7d2SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 101c915a7d2SJim Ingham if (log) 102b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 103b9c1b51eSKate Stone m_class_name.c_str()); 104c915a7d2SJim Ingham 105c915a7d2SJim Ingham bool is_stale = true; 106b9c1b51eSKate Stone if (m_implementation_sp) { 107b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 108b9c1b51eSKate Stone ->GetTarget() 109b9c1b51eSKate Stone .GetDebugger() 110b9c1b51eSKate Stone .GetCommandInterpreter() 111b9c1b51eSKate Stone .GetScriptInterpreter(); 112b9c1b51eSKate Stone if (script_interp) { 113c915a7d2SJim Ingham bool script_error; 114b9c1b51eSKate Stone is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp, 115b9c1b51eSKate Stone script_error); 116c915a7d2SJim Ingham if (script_error) 117c915a7d2SJim Ingham SetPlanComplete(false); 118c915a7d2SJim Ingham } 119c915a7d2SJim Ingham } 120c915a7d2SJim Ingham return is_stale; 121c915a7d2SJim Ingham } 122c915a7d2SJim Ingham 123b9c1b51eSKate Stone bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { 1242bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1252bdbfd50SJim Ingham if (log) 126b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 127b9c1b51eSKate Stone m_class_name.c_str()); 1282bdbfd50SJim Ingham 1292bdbfd50SJim Ingham bool explains_stop = true; 130b9c1b51eSKate Stone if (m_implementation_sp) { 131b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 132b9c1b51eSKate Stone ->GetTarget() 133b9c1b51eSKate Stone .GetDebugger() 134b9c1b51eSKate Stone .GetCommandInterpreter() 135b9c1b51eSKate Stone .GetScriptInterpreter(); 136b9c1b51eSKate Stone if (script_interp) { 1372bdbfd50SJim Ingham bool script_error; 138b9c1b51eSKate Stone explains_stop = script_interp->ScriptedThreadPlanExplainsStop( 139b9c1b51eSKate Stone m_implementation_sp, event_ptr, script_error); 1402bdbfd50SJim Ingham if (script_error) 1412bdbfd50SJim Ingham SetPlanComplete(false); 1422bdbfd50SJim Ingham } 1432bdbfd50SJim Ingham } 1442bdbfd50SJim Ingham return explains_stop; 1452bdbfd50SJim Ingham } 1462bdbfd50SJim Ingham 147b9c1b51eSKate Stone bool ThreadPlanPython::MischiefManaged() { 1482bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1492bdbfd50SJim Ingham if (log) 150b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 151b9c1b51eSKate Stone m_class_name.c_str()); 1522bdbfd50SJim Ingham bool mischief_managed = true; 153b9c1b51eSKate Stone if (m_implementation_sp) { 154b9c1b51eSKate Stone // I don't really need mischief_managed, since it's simpler to just call 155b9c1b51eSKate Stone // SetPlanComplete in should_stop. 1562bdbfd50SJim Ingham mischief_managed = IsPlanComplete(); 1572bdbfd50SJim Ingham if (mischief_managed) 1582bdbfd50SJim Ingham m_implementation_sp.reset(); 1592bdbfd50SJim Ingham } 1602bdbfd50SJim Ingham return mischief_managed; 1612bdbfd50SJim Ingham } 1622bdbfd50SJim Ingham 163b9c1b51eSKate Stone lldb::StateType ThreadPlanPython::GetPlanRunState() { 1642bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1652bdbfd50SJim Ingham if (log) 166b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 1672bdbfd50SJim Ingham m_class_name.c_str()); 1682bdbfd50SJim Ingham lldb::StateType run_state = eStateRunning; 169b9c1b51eSKate Stone if (m_implementation_sp) { 170b9c1b51eSKate Stone ScriptInterpreter *script_interp = m_thread.GetProcess() 171b9c1b51eSKate Stone ->GetTarget() 172b9c1b51eSKate Stone .GetDebugger() 173b9c1b51eSKate Stone .GetCommandInterpreter() 174b9c1b51eSKate Stone .GetScriptInterpreter(); 175b9c1b51eSKate Stone if (script_interp) { 1762bdbfd50SJim Ingham bool script_error; 177b9c1b51eSKate Stone run_state = script_interp->ScriptedThreadPlanGetRunState( 178b9c1b51eSKate Stone m_implementation_sp, script_error); 1792bdbfd50SJim Ingham } 1802bdbfd50SJim Ingham } 1812bdbfd50SJim Ingham return run_state; 1822bdbfd50SJim Ingham } 1832bdbfd50SJim Ingham 1842bdbfd50SJim Ingham // The ones below are not currently exported to Python. 1852bdbfd50SJim Ingham 186b9c1b51eSKate Stone bool ThreadPlanPython::StopOthers() { 187b9c1b51eSKate Stone // For now Python plans run all threads, but we should add some controls for 188b9c1b51eSKate Stone // this. 1892bdbfd50SJim Ingham return false; 1902bdbfd50SJim Ingham } 1912bdbfd50SJim Ingham 192b9c1b51eSKate Stone void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { 193b9c1b51eSKate Stone s->Printf("Python thread plan implemented by class %s.", 194b9c1b51eSKate Stone m_class_name.c_str()); 1952bdbfd50SJim Ingham } 1962bdbfd50SJim Ingham 197b9c1b51eSKate Stone bool ThreadPlanPython::WillStop() { 1982bdbfd50SJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 1992bdbfd50SJim Ingham if (log) 200b9c1b51eSKate Stone log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 201b9c1b51eSKate Stone m_class_name.c_str()); 2022bdbfd50SJim Ingham return true; 2032bdbfd50SJim Ingham } 204