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