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