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