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