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), m_did_push(false) { 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 if (!m_did_push) 47 return true; 48 49 if (!m_implementation_sp) { 50 if (error) 51 error->Printf("Python thread plan does not have an implementation"); 52 return false; 53 } 54 55 return true; 56 } 57 58 void ThreadPlanPython::DidPush() { 59 // We set up the script side in DidPush, so that it can push other plans in 60 // the constructor, and doesn't have to care about the details of DidPush. 61 m_did_push = true; 62 if (!m_class_name.empty()) { 63 ScriptInterpreter *script_interp = m_thread.GetProcess() 64 ->GetTarget() 65 .GetDebugger() 66 .GetCommandInterpreter() 67 .GetScriptInterpreter(); 68 if (script_interp) { 69 m_implementation_sp = script_interp->CreateScriptedThreadPlan( 70 m_class_name.c_str(), this->shared_from_this()); 71 } 72 } 73 } 74 75 bool ThreadPlanPython::ShouldStop(Event *event_ptr) { 76 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 77 if (log) 78 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 79 m_class_name.c_str()); 80 81 bool should_stop = true; 82 if (m_implementation_sp) { 83 ScriptInterpreter *script_interp = m_thread.GetProcess() 84 ->GetTarget() 85 .GetDebugger() 86 .GetCommandInterpreter() 87 .GetScriptInterpreter(); 88 if (script_interp) { 89 bool script_error; 90 should_stop = script_interp->ScriptedThreadPlanShouldStop( 91 m_implementation_sp, event_ptr, script_error); 92 if (script_error) 93 SetPlanComplete(false); 94 } 95 } 96 return should_stop; 97 } 98 99 bool ThreadPlanPython::IsPlanStale() { 100 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 101 if (log) 102 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 103 m_class_name.c_str()); 104 105 bool is_stale = true; 106 if (m_implementation_sp) { 107 ScriptInterpreter *script_interp = m_thread.GetProcess() 108 ->GetTarget() 109 .GetDebugger() 110 .GetCommandInterpreter() 111 .GetScriptInterpreter(); 112 if (script_interp) { 113 bool script_error; 114 is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp, 115 script_error); 116 if (script_error) 117 SetPlanComplete(false); 118 } 119 } 120 return is_stale; 121 } 122 123 bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { 124 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 125 if (log) 126 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 127 m_class_name.c_str()); 128 129 bool explains_stop = true; 130 if (m_implementation_sp) { 131 ScriptInterpreter *script_interp = m_thread.GetProcess() 132 ->GetTarget() 133 .GetDebugger() 134 .GetCommandInterpreter() 135 .GetScriptInterpreter(); 136 if (script_interp) { 137 bool script_error; 138 explains_stop = script_interp->ScriptedThreadPlanExplainsStop( 139 m_implementation_sp, event_ptr, script_error); 140 if (script_error) 141 SetPlanComplete(false); 142 } 143 } 144 return explains_stop; 145 } 146 147 bool ThreadPlanPython::MischiefManaged() { 148 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 149 if (log) 150 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 151 m_class_name.c_str()); 152 bool mischief_managed = true; 153 if (m_implementation_sp) { 154 // I don't really need mischief_managed, since it's simpler to just call 155 // SetPlanComplete in should_stop. 156 mischief_managed = IsPlanComplete(); 157 if (mischief_managed) 158 m_implementation_sp.reset(); 159 } 160 return mischief_managed; 161 } 162 163 lldb::StateType ThreadPlanPython::GetPlanRunState() { 164 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 165 if (log) 166 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 167 m_class_name.c_str()); 168 lldb::StateType run_state = eStateRunning; 169 if (m_implementation_sp) { 170 ScriptInterpreter *script_interp = m_thread.GetProcess() 171 ->GetTarget() 172 .GetDebugger() 173 .GetCommandInterpreter() 174 .GetScriptInterpreter(); 175 if (script_interp) { 176 bool script_error; 177 run_state = script_interp->ScriptedThreadPlanGetRunState( 178 m_implementation_sp, script_error); 179 } 180 } 181 return run_state; 182 } 183 184 // The ones below are not currently exported to Python. 185 186 bool ThreadPlanPython::StopOthers() { 187 // For now Python plans run all threads, but we should add some controls for 188 // this. 189 return false; 190 } 191 192 void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { 193 s->Printf("Python thread plan implemented by class %s.", 194 m_class_name.c_str()); 195 } 196 197 bool ThreadPlanPython::WillStop() { 198 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 199 if (log) 200 log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 201 m_class_name.c_str()); 202 return true; 203 } 204