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