1 //===-- ThreadPlanPython.cpp ----------------------------------------------===// 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/LLDBLog.h" 21 #include "lldb/Utility/Log.h" 22 #include "lldb/Utility/State.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 // ThreadPlanPython 28 29 ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name, 30 const StructuredDataImpl &args_data) 31 : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread, 32 eVoteNoOpinion, eVoteNoOpinion), 33 m_class_name(class_name), m_args_data(args_data), m_did_push(false), 34 m_stop_others(false) { 35 SetIsControllingPlan(true); 36 SetOkayToDiscard(true); 37 SetPrivate(false); 38 } 39 40 bool ThreadPlanPython::ValidatePlan(Stream *error) { 41 if (!m_did_push) 42 return true; 43 44 if (!m_implementation_sp) { 45 if (error) 46 error->Printf("Error constructing Python ThreadPlan: %s", 47 m_error_str.empty() ? "<unknown error>" 48 : m_error_str.c_str()); 49 return false; 50 } 51 52 return true; 53 } 54 55 ScriptInterpreter *ThreadPlanPython::GetScriptInterpreter() { 56 return m_process.GetTarget().GetDebugger().GetScriptInterpreter(); 57 } 58 59 void ThreadPlanPython::DidPush() { 60 // We set up the script side in DidPush, so that it can push other plans in 61 // the constructor, and doesn't have to care about the details of DidPush. 62 m_did_push = true; 63 if (!m_class_name.empty()) { 64 ScriptInterpreter *script_interp = GetScriptInterpreter(); 65 if (script_interp) { 66 m_implementation_sp = script_interp->CreateScriptedThreadPlan( 67 m_class_name.c_str(), m_args_data, m_error_str, 68 this->shared_from_this()); 69 } 70 } 71 } 72 73 bool ThreadPlanPython::ShouldStop(Event *event_ptr) { 74 Log *log = GetLog(LLDBLog::Thread); 75 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 76 m_class_name.c_str()); 77 78 bool should_stop = true; 79 if (m_implementation_sp) { 80 ScriptInterpreter *script_interp = GetScriptInterpreter(); 81 if (script_interp) { 82 bool script_error; 83 should_stop = script_interp->ScriptedThreadPlanShouldStop( 84 m_implementation_sp, event_ptr, script_error); 85 if (script_error) 86 SetPlanComplete(false); 87 } 88 } 89 return should_stop; 90 } 91 92 bool ThreadPlanPython::IsPlanStale() { 93 Log *log = GetLog(LLDBLog::Thread); 94 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 95 m_class_name.c_str()); 96 97 bool is_stale = true; 98 if (m_implementation_sp) { 99 ScriptInterpreter *script_interp = GetScriptInterpreter(); 100 if (script_interp) { 101 bool script_error; 102 is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp, 103 script_error); 104 if (script_error) 105 SetPlanComplete(false); 106 } 107 } 108 return is_stale; 109 } 110 111 bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { 112 Log *log = GetLog(LLDBLog::Thread); 113 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 114 m_class_name.c_str()); 115 116 bool explains_stop = true; 117 if (m_implementation_sp) { 118 ScriptInterpreter *script_interp = GetScriptInterpreter(); 119 if (script_interp) { 120 bool script_error; 121 explains_stop = script_interp->ScriptedThreadPlanExplainsStop( 122 m_implementation_sp, event_ptr, script_error); 123 if (script_error) 124 SetPlanComplete(false); 125 } 126 } 127 return explains_stop; 128 } 129 130 bool ThreadPlanPython::MischiefManaged() { 131 Log *log = GetLog(LLDBLog::Thread); 132 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 133 m_class_name.c_str()); 134 bool mischief_managed = true; 135 if (m_implementation_sp) { 136 // I don't really need mischief_managed, since it's simpler to just call 137 // SetPlanComplete in should_stop. 138 mischief_managed = IsPlanComplete(); 139 if (mischief_managed) 140 m_implementation_sp.reset(); 141 } 142 return mischief_managed; 143 } 144 145 lldb::StateType ThreadPlanPython::GetPlanRunState() { 146 Log *log = GetLog(LLDBLog::Thread); 147 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 148 m_class_name.c_str()); 149 lldb::StateType run_state = eStateRunning; 150 if (m_implementation_sp) { 151 ScriptInterpreter *script_interp = GetScriptInterpreter(); 152 if (script_interp) { 153 bool script_error; 154 run_state = script_interp->ScriptedThreadPlanGetRunState( 155 m_implementation_sp, script_error); 156 } 157 } 158 return run_state; 159 } 160 161 // The ones below are not currently exported to Python. 162 void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { 163 s->Printf("Python thread plan implemented by class %s.", 164 m_class_name.c_str()); 165 } 166 167 bool ThreadPlanPython::WillStop() { 168 Log *log = GetLog(LLDBLog::Thread); 169 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 170 m_class_name.c_str()); 171 return true; 172 } 173