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