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