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 23using namespace lldb; 24using namespace lldb_private; 25 26// ThreadPlanPython 27 28ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name, 29 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 SetIsMasterPlan(true); 34 SetOkayToDiscard(true); 35 SetPrivate(false); 36} 37 38ThreadPlanPython::~ThreadPlanPython() { 39 // FIXME, do I need to decrement the ref count on this implementation object 40 // to make it go away? 41} 42 43bool ThreadPlanPython::ValidatePlan(Stream *error) { 44 if (!m_did_push) 45 return true; 46 47 if (!m_implementation_sp) { 48 if (error) 49 error->Printf("Error constructing Python ThreadPlan: %s", 50 m_error_str.empty() ? "<unknown error>" 51 : m_error_str.c_str()); 52 return false; 53 } 54 55 return true; 56} 57 58void 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 = m_thread.GetProcess() 64 ->GetTarget() 65 .GetDebugger() 66 .GetScriptInterpreter(); 67 if (script_interp) { 68 m_implementation_sp = script_interp->CreateScriptedThreadPlan( 69 m_class_name.c_str(), m_args_data, m_error_str, 70 this->shared_from_this()); 71 } 72 } 73} 74 75bool ThreadPlanPython::ShouldStop(Event *event_ptr) { 76 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 77 LLDB_LOGF(log, "%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 .GetScriptInterpreter(); 86 if (script_interp) { 87 bool script_error; 88 should_stop = script_interp->ScriptedThreadPlanShouldStop( 89 m_implementation_sp, event_ptr, script_error); 90 if (script_error) 91 SetPlanComplete(false); 92 } 93 } 94 return should_stop; 95} 96 97bool ThreadPlanPython::IsPlanStale() { 98 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 99 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 100 m_class_name.c_str()); 101 102 bool is_stale = true; 103 if (m_implementation_sp) { 104 ScriptInterpreter *script_interp = m_thread.GetProcess() 105 ->GetTarget() 106 .GetDebugger() 107 .GetScriptInterpreter(); 108 if (script_interp) { 109 bool script_error; 110 is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp, 111 script_error); 112 if (script_error) 113 SetPlanComplete(false); 114 } 115 } 116 return is_stale; 117} 118 119bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) { 120 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 121 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 122 m_class_name.c_str()); 123 124 bool explains_stop = true; 125 if (m_implementation_sp) { 126 ScriptInterpreter *script_interp = m_thread.GetProcess() 127 ->GetTarget() 128 .GetDebugger() 129 .GetScriptInterpreter(); 130 if (script_interp) { 131 bool script_error; 132 explains_stop = script_interp->ScriptedThreadPlanExplainsStop( 133 m_implementation_sp, event_ptr, script_error); 134 if (script_error) 135 SetPlanComplete(false); 136 } 137 } 138 return explains_stop; 139} 140 141bool ThreadPlanPython::MischiefManaged() { 142 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 143 LLDB_LOGF(log, "%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 156lldb::StateType ThreadPlanPython::GetPlanRunState() { 157 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 158 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 159 m_class_name.c_str()); 160 lldb::StateType run_state = eStateRunning; 161 if (m_implementation_sp) { 162 ScriptInterpreter *script_interp = m_thread.GetProcess() 163 ->GetTarget() 164 .GetDebugger() 165 .GetScriptInterpreter(); 166 if (script_interp) { 167 bool script_error; 168 run_state = script_interp->ScriptedThreadPlanGetRunState( 169 m_implementation_sp, script_error); 170 } 171 } 172 return run_state; 173} 174 175// The ones below are not currently exported to Python. 176 177bool ThreadPlanPython::StopOthers() { 178 // For now Python plans run all threads, but we should add some controls for 179 // this. 180 return false; 181} 182 183void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) { 184 s->Printf("Python thread plan implemented by class %s.", 185 m_class_name.c_str()); 186} 187 188bool ThreadPlanPython::WillStop() { 189 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 190 LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION, 191 m_class_name.c_str()); 192 return true; 193} 194