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