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