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 __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::DoPlanExplainsStop (Event *event_ptr) 105 { 106 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 107 if (log) 108 log->Printf ("%s called on Python Thread Plan: %s )", 109 __PRETTY_FUNCTION__, m_class_name.c_str()); 110 111 bool explains_stop = 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 explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error); 119 if (script_error) 120 SetPlanComplete(false); 121 } 122 } 123 return explains_stop; 124 } 125 126 bool 127 ThreadPlanPython::MischiefManaged () 128 { 129 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 130 if (log) 131 log->Printf ("%s called on Python Thread Plan: %s )", 132 __PRETTY_FUNCTION__, m_class_name.c_str()); 133 bool mischief_managed = true; 134 if (m_implementation_sp) 135 { 136 // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop. 137 mischief_managed = IsPlanComplete(); 138 if (mischief_managed) 139 m_implementation_sp.reset(); 140 } 141 return mischief_managed; 142 } 143 144 lldb::StateType 145 ThreadPlanPython::GetPlanRunState () 146 { 147 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 148 if (log) 149 log->Printf ("%s called on Python Thread Plan: %s )", 150 __PRETTY_FUNCTION__, 151 m_class_name.c_str()); 152 lldb::StateType run_state = eStateRunning; 153 if (m_implementation_sp) 154 { 155 ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 156 if (script_interp) 157 { 158 bool script_error; 159 run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error); 160 } 161 } 162 return run_state; 163 } 164 165 // The ones below are not currently exported to Python. 166 167 bool 168 ThreadPlanPython::StopOthers () 169 { 170 // For now Python plans run all threads, but we should add some controls for this. 171 return false; 172 } 173 174 void 175 ThreadPlanPython::GetDescription (Stream *s, 176 lldb::DescriptionLevel level) 177 { 178 s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str()); 179 } 180 181 bool 182 ThreadPlanPython::WillStop () 183 { 184 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 185 if (log) 186 log->Printf ("%s called on Python Thread Plan: %s )", 187 __PRETTY_FUNCTION__, m_class_name.c_str()); 188 return true; 189 } 190