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