1 //===-- ThreadPlanPython.cpp ------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Target/ThreadPlan.h" 11 12 #include "lldb/Core/Debugger.h" 13 #include "lldb/Interpreter/CommandInterpreter.h" 14 #include "lldb/Interpreter/ScriptInterpreter.h" 15 #include "lldb/Target/Process.h" 16 #include "lldb/Target/RegisterContext.h" 17 #include "lldb/Target/Target.h" 18 #include "lldb/Target/Thread.h" 19 #include "lldb/Target/ThreadPlan.h" 20 #include "lldb/Target/ThreadPlanPython.h" 21 #include "lldb/Utility/Log.h" 22 #include "lldb/Utility/State.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 //---------------------------------------------------------------------- 28 // ThreadPlanPython 29 //---------------------------------------------------------------------- 30 31 ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name) 32 : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread, 33 eVoteNoOpinion, eVoteNoOpinion), 34 m_class_name(class_name) { 35 SetIsMasterPlan(true); 36 SetOkayToDiscard(true); 37 SetPrivate(false); 38 } 39 40 ThreadPlanPython::~ThreadPlanPython() { 41 // FIXME, do I need to decrement the ref count on this implementation object 42 // to make it go away? 43 } 44 45 bool ThreadPlanPython::ValidatePlan(Stream *error) { 46 // I have to postpone setting up the implementation till after the constructor 47 // because I need to call 48 // shared_from_this, which you can't do in the constructor. So I'll do it 49 // here. 50 if (m_implementation_sp) 51 return true; 52 else 53 return false; 54 } 55 56 void ThreadPlanPython::DidPush() { 57 // We set up the script side in DidPush, so that it can push other plans in 58 // the constructor, and doesn't have to care about the details of DidPush. 59 60 if (!m_class_name.empty()) { 61 ScriptInterpreter *script_interp = m_thread.GetProcess() 62 ->GetTarget() 63 .GetDebugger() 64 .GetCommandInterpreter() 65 .GetScriptInterpreter(); 66 if (script_interp) { 67 m_implementation_sp = script_interp->CreateScriptedThreadPlan( 68 m_class_name.c_str(), this->shared_from_this()); 69 } 70 } 71 } 72 73 bool ThreadPlanPython::ShouldStop(Event *event_ptr) { 74 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 75 if (log) 76 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 77 m_class_name.c_str()); 78 79 bool should_stop = true; 80 if (m_implementation_sp) { 81 ScriptInterpreter *script_interp = m_thread.GetProcess() 82 ->GetTarget() 83 .GetDebugger() 84 .GetCommandInterpreter() 85 .GetScriptInterpreter(); 86 if (script_interp) { 87 bool script_error; 88 should_stop = script_interp->ScriptedThreadPlanShouldStop( 89 m_implementation_sp, event_ptr, script_error); 90 if (script_error) 91 SetPlanComplete(false); 92 } 93 } 94 return should_stop; 95 } 96 97 bool ThreadPlanPython::IsPlanStale() { 98 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 99 if (log) 100 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 101 m_class_name.c_str()); 102 103 bool is_stale = true; 104 if (m_implementation_sp) { 105 ScriptInterpreter *script_interp = m_thread.GetProcess() 106 ->GetTarget() 107 .GetDebugger() 108 .GetCommandInterpreter() 109 .GetScriptInterpreter(); 110 if (script_interp) { 111 bool script_error; 112 is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp, 113 script_error); 114 if (script_error) 115 SetPlanComplete(false); 116 } 117 } 118 return is_stale; 119 } 120 121 bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { 122 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 123 if (log) 124 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 125 m_class_name.c_str()); 126 127 bool explains_stop = true; 128 if (m_implementation_sp) { 129 ScriptInterpreter *script_interp = m_thread.GetProcess() 130 ->GetTarget() 131 .GetDebugger() 132 .GetCommandInterpreter() 133 .GetScriptInterpreter(); 134 if (script_interp) { 135 bool script_error; 136 explains_stop = script_interp->ScriptedThreadPlanExplainsStop( 137 m_implementation_sp, event_ptr, script_error); 138 if (script_error) 139 SetPlanComplete(false); 140 } 141 } 142 return explains_stop; 143 } 144 145 bool ThreadPlanPython::MischiefManaged() { 146 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 147 if (log) 148 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 149 m_class_name.c_str()); 150 bool mischief_managed = true; 151 if (m_implementation_sp) { 152 // I don't really need mischief_managed, since it's simpler to just call 153 // SetPlanComplete in should_stop. 154 mischief_managed = IsPlanComplete(); 155 if (mischief_managed) 156 m_implementation_sp.reset(); 157 } 158 return mischief_managed; 159 } 160 161 lldb::StateType ThreadPlanPython::GetPlanRunState() { 162 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 163 if (log) 164 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 165 m_class_name.c_str()); 166 lldb::StateType run_state = eStateRunning; 167 if (m_implementation_sp) { 168 ScriptInterpreter *script_interp = m_thread.GetProcess() 169 ->GetTarget() 170 .GetDebugger() 171 .GetCommandInterpreter() 172 .GetScriptInterpreter(); 173 if (script_interp) { 174 bool script_error; 175 run_state = script_interp->ScriptedThreadPlanGetRunState( 176 m_implementation_sp, script_error); 177 } 178 } 179 return run_state; 180 } 181 182 // The ones below are not currently exported to Python. 183 184 bool ThreadPlanPython::StopOthers() { 185 // For now Python plans run all threads, but we should add some controls for 186 // this. 187 return false; 188 } 189 190 void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { 191 s->Printf("Python thread plan implemented by class %s.", 192 m_class_name.c_str()); 193 } 194 195 bool ThreadPlanPython::WillStop() { 196 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 197 if (log) 198 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 199 m_class_name.c_str()); 200 return true; 201 } 202