1 //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/lldb-python.h" 11 12 #include "lldb/Target/ThreadPlan.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/Log.h" 20 #include "lldb/Core/State.h" 21 #include "lldb/Target/RegisterContext.h" 22 #include "lldb/Target/Thread.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Utility/ConvertEnum.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 //---------------------------------------------------------------------- 31 // ThreadPlan constructor 32 //---------------------------------------------------------------------- 33 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) : 34 m_thread (thread), 35 m_stop_vote (stop_vote), 36 m_run_vote (run_vote), 37 m_kind (kind), 38 m_name (name), 39 m_plan_complete_mutex (Mutex::eMutexTypeRecursive), 40 m_cached_plan_explains_stop (eLazyBoolCalculate), 41 m_plan_complete (false), 42 m_plan_private (false), 43 m_okay_to_discard (true), 44 m_is_master_plan (false), 45 m_plan_succeeded(true) 46 { 47 SetID (GetNextID()); 48 } 49 50 //---------------------------------------------------------------------- 51 // Destructor 52 //---------------------------------------------------------------------- 53 ThreadPlan::~ThreadPlan() 54 { 55 } 56 57 bool 58 ThreadPlan::PlanExplainsStop (Event *event_ptr) 59 { 60 if (m_cached_plan_explains_stop == eLazyBoolCalculate) 61 { 62 bool actual_value = DoPlanExplainsStop(event_ptr); 63 m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo; 64 return actual_value; 65 } 66 else 67 { 68 return m_cached_plan_explains_stop == eLazyBoolYes; 69 } 70 } 71 72 bool 73 ThreadPlan::IsPlanComplete () 74 { 75 Mutex::Locker locker(m_plan_complete_mutex); 76 return m_plan_complete; 77 } 78 79 void 80 ThreadPlan::SetPlanComplete (bool success) 81 { 82 Mutex::Locker locker(m_plan_complete_mutex); 83 m_plan_complete = true; 84 m_plan_succeeded = success; 85 } 86 87 bool 88 ThreadPlan::MischiefManaged () 89 { 90 Mutex::Locker locker(m_plan_complete_mutex); 91 // Mark the plan is complete, but don't override the success flag. 92 m_plan_complete = true; 93 return true; 94 } 95 96 Vote 97 ThreadPlan::ShouldReportStop (Event *event_ptr) 98 { 99 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 100 101 if (m_stop_vote == eVoteNoOpinion) 102 { 103 ThreadPlan *prev_plan = GetPreviousPlan (); 104 if (prev_plan) 105 { 106 Vote prev_vote = prev_plan->ShouldReportStop (event_ptr); 107 if (log) 108 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s", 109 GetVoteAsCString (prev_vote)); 110 return prev_vote; 111 } 112 } 113 if (log) 114 log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote)); 115 return m_stop_vote; 116 } 117 118 Vote 119 ThreadPlan::ShouldReportRun (Event *event_ptr) 120 { 121 if (m_run_vote == eVoteNoOpinion) 122 { 123 ThreadPlan *prev_plan = GetPreviousPlan (); 124 if (prev_plan) 125 return prev_plan->ShouldReportRun (event_ptr); 126 } 127 return m_run_vote; 128 } 129 130 bool 131 ThreadPlan::StopOthers () 132 { 133 ThreadPlan *prev_plan; 134 prev_plan = GetPreviousPlan (); 135 if (prev_plan == NULL) 136 return false; 137 else 138 return prev_plan->StopOthers(); 139 } 140 141 void 142 ThreadPlan::SetStopOthers (bool new_value) 143 { 144 // SetStopOthers doesn't work up the hierarchy. You have to set the 145 // explicit ThreadPlan you want to affect. 146 } 147 148 bool 149 ThreadPlan::WillResume (StateType resume_state, bool current_plan) 150 { 151 m_cached_plan_explains_stop = eLazyBoolCalculate; 152 153 if (current_plan) 154 { 155 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 156 157 if (log) 158 { 159 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 160 assert (reg_ctx); 161 addr_t pc = reg_ctx->GetPC(); 162 addr_t sp = reg_ctx->GetSP(); 163 addr_t fp = reg_ctx->GetFP(); 164 log->Printf("%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", " 165 "plan = '%s', state = %s, stop others = %d", 166 __FUNCTION__, m_thread.GetIndexID(), 167 static_cast<void*>(&m_thread), m_thread.GetID(), 168 static_cast<uint64_t>(pc), static_cast<uint64_t>(sp), 169 static_cast<uint64_t>(fp), m_name.c_str(), 170 StateAsCString(resume_state), StopOthers()); 171 } 172 } 173 return DoWillResume (resume_state, current_plan); 174 } 175 176 lldb::user_id_t 177 ThreadPlan::GetNextID() 178 { 179 static uint32_t g_nextPlanID = 0; 180 return ++g_nextPlanID; 181 } 182 183 void 184 ThreadPlan::DidPush() 185 { 186 } 187 188 void 189 ThreadPlan::WillPop() 190 { 191 } 192 193 bool 194 ThreadPlan::OkayToDiscard() 195 { 196 if (!IsMasterPlan()) 197 return true; 198 else 199 return m_okay_to_discard; 200 } 201 202 lldb::StateType 203 ThreadPlan::RunState () 204 { 205 if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled()) 206 return eStateStepping; 207 else 208 return GetPlanRunState(); 209 } 210 211 //---------------------------------------------------------------------- 212 // ThreadPlanNull 213 //---------------------------------------------------------------------- 214 215 ThreadPlanNull::ThreadPlanNull (Thread &thread) : 216 ThreadPlan (ThreadPlan::eKindNull, 217 "Null Thread Plan", 218 thread, 219 eVoteNoOpinion, 220 eVoteNoOpinion) 221 { 222 } 223 224 ThreadPlanNull::~ThreadPlanNull () 225 { 226 } 227 228 void 229 ThreadPlanNull::GetDescription (Stream *s, 230 lldb::DescriptionLevel level) 231 { 232 s->PutCString("Null thread plan - thread has been destroyed."); 233 } 234 235 bool 236 ThreadPlanNull::ValidatePlan (Stream *error) 237 { 238 #ifdef LLDB_CONFIGURATION_DEBUG 239 fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 240 __PRETTY_FUNCTION__, 241 m_thread.GetID(), 242 m_thread.GetProtocolID()); 243 #else 244 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 245 if (log) 246 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 247 __PRETTY_FUNCTION__, 248 m_thread.GetID(), 249 m_thread.GetProtocolID()); 250 #endif 251 return true; 252 } 253 254 bool 255 ThreadPlanNull::ShouldStop (Event *event_ptr) 256 { 257 #ifdef LLDB_CONFIGURATION_DEBUG 258 fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 259 __PRETTY_FUNCTION__, 260 m_thread.GetID(), 261 m_thread.GetProtocolID()); 262 #else 263 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 264 if (log) 265 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 266 __PRETTY_FUNCTION__, 267 m_thread.GetID(), 268 m_thread.GetProtocolID()); 269 #endif 270 return true; 271 } 272 273 bool 274 ThreadPlanNull::WillStop () 275 { 276 #ifdef LLDB_CONFIGURATION_DEBUG 277 fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 278 __PRETTY_FUNCTION__, 279 m_thread.GetID(), 280 m_thread.GetProtocolID()); 281 #else 282 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 283 if (log) 284 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 285 __PRETTY_FUNCTION__, 286 m_thread.GetID(), 287 m_thread.GetProtocolID()); 288 #endif 289 return true; 290 } 291 292 bool 293 ThreadPlanNull::DoPlanExplainsStop (Event *event_ptr) 294 { 295 #ifdef LLDB_CONFIGURATION_DEBUG 296 fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 297 __PRETTY_FUNCTION__, 298 m_thread.GetID(), 299 m_thread.GetProtocolID()); 300 #else 301 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 302 if (log) 303 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 304 __PRETTY_FUNCTION__, 305 m_thread.GetID(), 306 m_thread.GetProtocolID()); 307 #endif 308 return true; 309 } 310 311 // The null plan is never done. 312 bool 313 ThreadPlanNull::MischiefManaged () 314 { 315 // The null plan is never done. 316 #ifdef LLDB_CONFIGURATION_DEBUG 317 fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 318 __PRETTY_FUNCTION__, 319 m_thread.GetID(), 320 m_thread.GetProtocolID()); 321 #else 322 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 323 if (log) 324 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 325 __PRETTY_FUNCTION__, 326 m_thread.GetID(), 327 m_thread.GetProtocolID()); 328 #endif 329 return false; 330 } 331 332 lldb::StateType 333 ThreadPlanNull::GetPlanRunState () 334 { 335 // Not sure what to return here. This is a dead thread. 336 #ifdef LLDB_CONFIGURATION_DEBUG 337 fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 338 __PRETTY_FUNCTION__, 339 m_thread.GetID(), 340 m_thread.GetProtocolID()); 341 #else 342 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); 343 if (log) 344 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")", 345 __PRETTY_FUNCTION__, 346 m_thread.GetID(), 347 m_thread.GetProtocolID()); 348 #endif 349 return eStateRunning; 350 } 351