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