1 //===-- ThreadPlanStepInRange.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/ThreadPlanStepInRange.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 17 #include "lldb/lldb-private-log.h" 18 #include "lldb/Core/Log.h" 19 #include "lldb/Core/Module.h" 20 #include "lldb/Core/Stream.h" 21 #include "lldb/Symbol/Symbol.h" 22 #include "lldb/Symbol/Function.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/RegisterContext.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/ThreadPlanStepOut.h" 28 #include "lldb/Target/ThreadPlanStepThrough.h" 29 #include "lldb/Core/RegularExpression.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug; 35 36 //---------------------------------------------------------------------- 37 // ThreadPlanStepInRange: Step through a stack range, either stepping over or into 38 // based on the value of \a type. 39 //---------------------------------------------------------------------- 40 41 ThreadPlanStepInRange::ThreadPlanStepInRange 42 ( 43 Thread &thread, 44 const AddressRange &range, 45 const SymbolContext &addr_context, 46 lldb::RunMode stop_others 47 ) : 48 ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 49 ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 50 m_step_past_prologue (true), 51 m_virtual_step (false) 52 { 53 SetFlagsToDefault (); 54 } 55 56 ThreadPlanStepInRange::ThreadPlanStepInRange 57 ( 58 Thread &thread, 59 const AddressRange &range, 60 const SymbolContext &addr_context, 61 const char *step_into_target, 62 lldb::RunMode stop_others 63 ) : 64 ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 65 ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 66 m_step_past_prologue (true), 67 m_virtual_step (false), 68 m_step_into_target (step_into_target) 69 { 70 SetFlagsToDefault (); 71 } 72 73 ThreadPlanStepInRange::~ThreadPlanStepInRange () 74 { 75 } 76 77 void 78 ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) 79 { 80 if (level == lldb::eDescriptionLevelBrief) 81 s->Printf("step in"); 82 else 83 { 84 s->Printf ("Stepping through range (stepping into functions): "); 85 DumpRanges(s); 86 const char *step_into_target = m_step_into_target.AsCString(); 87 if (step_into_target && step_into_target[0] != '\0') 88 s->Printf (" targeting %s.", m_step_into_target.AsCString()); 89 else 90 s->PutChar('.'); 91 } 92 } 93 94 bool 95 ThreadPlanStepInRange::ShouldStop (Event *event_ptr) 96 { 97 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 98 99 if (log) 100 { 101 StreamString s; 102 s.Address (m_thread.GetRegisterContext()->GetPC(), 103 m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 104 log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); 105 } 106 107 if (IsPlanComplete()) 108 return true; 109 110 m_no_more_plans = false; 111 if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete()) 112 { 113 if (!m_sub_plan_sp->PlanSucceeded()) 114 { 115 SetPlanComplete(); 116 m_no_more_plans = true; 117 return true; 118 } 119 else 120 m_sub_plan_sp.reset(); 121 } 122 123 if (m_virtual_step) 124 { 125 // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise 126 // we're done. 127 m_sub_plan_sp = InvokeShouldStopHereCallback(); 128 } 129 else 130 { 131 // Stepping through should be done running other threads in general, since we're setting a breakpoint and 132 // continuing. So only stop others if we are explicitly told to do so. 133 134 bool stop_others; 135 if (m_stop_others == lldb::eOnlyThisThread) 136 stop_others = true; 137 else 138 stop_others = false; 139 140 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 141 142 if (frame_order == eFrameCompareOlder) 143 { 144 // If we're in an older frame then we should stop. 145 // 146 // A caveat to this is if we think the frame is older but we're actually in a trampoline. 147 // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are 148 // in a trampoline we think the frame is older because the trampoline confused the backtracer. 149 m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 150 if (!m_sub_plan_sp) 151 return true; 152 else if (log) 153 { 154 log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); 155 } 156 157 } 158 else if (frame_order == eFrameCompareEqual && InSymbol()) 159 { 160 // If we are not in a place we should step through, we're done. 161 // One tricky bit here is that some stubs don't push a frame, so we have to check 162 // both the case of a frame that is younger, or the same as this frame. 163 // However, if the frame is the same, and we are still in the symbol we started 164 // in, the we don't need to do this. This first check isn't strictly necessary, 165 // but it is more efficient. 166 167 // If we're still in the range, keep going, either by running to the next branch breakpoint, or by 168 // stepping. 169 if (InRange()) 170 { 171 SetNextBranchBreakpoint(); 172 return false; 173 } 174 175 SetPlanComplete(); 176 m_no_more_plans = true; 177 return true; 178 } 179 180 // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: 181 ClearNextBranchBreakpoint(); 182 183 // We may have set the plan up above in the FrameIsOlder section: 184 185 if (!m_sub_plan_sp) 186 m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 187 188 if (log) 189 { 190 if (m_sub_plan_sp) 191 log->Printf ("Found a step through plan: %s", m_sub_plan_sp->GetName()); 192 else 193 log->Printf ("No step through plan found."); 194 } 195 196 // If not, give the "should_stop" callback a chance to push a plan to get us out of here. 197 // But only do that if we actually have stepped in. 198 if (!m_sub_plan_sp && frame_order == eFrameCompareYounger) 199 m_sub_plan_sp = InvokeShouldStopHereCallback(); 200 201 // If we've stepped in and we are going to stop here, check to see if we were asked to 202 // run past the prologue, and if so do that. 203 204 if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && m_step_past_prologue) 205 { 206 lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); 207 if (curr_frame) 208 { 209 size_t bytes_to_skip = 0; 210 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); 211 Address func_start_address; 212 213 SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); 214 215 if (sc.function) 216 { 217 func_start_address = sc.function->GetAddressRange().GetBaseAddress(); 218 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 219 bytes_to_skip = sc.function->GetPrologueByteSize(); 220 } 221 else if (sc.symbol) 222 { 223 func_start_address = sc.symbol->GetAddress(); 224 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 225 bytes_to_skip = sc.symbol->GetPrologueByteSize(); 226 } 227 228 if (bytes_to_skip != 0) 229 { 230 func_start_address.Slide (bytes_to_skip); 231 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 232 if (log) 233 log->Printf ("Pushing past prologue "); 234 235 m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); 236 } 237 } 238 } 239 } 240 241 if (!m_sub_plan_sp) 242 { 243 m_no_more_plans = true; 244 SetPlanComplete(); 245 return true; 246 } 247 else 248 { 249 m_no_more_plans = false; 250 return false; 251 } 252 } 253 254 void 255 ThreadPlanStepInRange::SetFlagsToDefault () 256 { 257 GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); 258 } 259 260 void 261 ThreadPlanStepInRange::SetAvoidRegexp(const char *name) 262 { 263 if (m_avoid_regexp_ap.get() == NULL) 264 m_avoid_regexp_ap.reset (new RegularExpression(name)); 265 266 m_avoid_regexp_ap->Compile (name); 267 } 268 269 void 270 ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) 271 { 272 // TODO: Should we test this for sanity? 273 ThreadPlanStepInRange::s_default_flag_values = new_value; 274 } 275 276 bool 277 ThreadPlanStepInRange::FrameMatchesAvoidCriteria () 278 { 279 StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); 280 281 // Check the library list first, as that's cheapest: 282 bool libraries_say_avoid = false; 283 284 FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid()); 285 size_t num_libraries = libraries_to_avoid.GetSize(); 286 if (num_libraries > 0) 287 { 288 SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); 289 FileSpec frame_library(sc.module_sp->GetFileSpec()); 290 291 if (frame_library) 292 { 293 for (size_t i = 0; i < num_libraries; i++) 294 { 295 const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); 296 if (FileSpec::Equal (file_spec, frame_library, false)) 297 { 298 libraries_say_avoid = true; 299 break; 300 } 301 } 302 } 303 } 304 if (libraries_say_avoid) 305 return true; 306 307 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 308 if (avoid_regexp_to_use == NULL) 309 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 310 311 if (avoid_regexp_to_use != NULL) 312 { 313 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 314 if (sc.symbol != NULL) 315 { 316 const char *frame_function_name = sc.GetFunctionName().GetCString(); 317 if (frame_function_name) 318 { 319 size_t num_matches = 0; 320 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 321 if (log) 322 num_matches = 1; 323 324 RegularExpression::Match regex_match(num_matches); 325 326 bool return_value = avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); 327 if (return_value) 328 { 329 if (log) 330 { 331 std::string match; 332 regex_match.GetMatchAtIndex(frame_function_name,0, match); 333 log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".", 334 frame_function_name, 335 avoid_regexp_to_use->GetText(), 336 match.c_str()); 337 } 338 339 } 340 return return_value; 341 } 342 } 343 } 344 return false; 345 } 346 347 ThreadPlanSP 348 ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton) 349 { 350 bool should_step_out = false; 351 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 352 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 353 354 if (flags.Test(eAvoidNoDebug)) 355 { 356 if (!frame->HasDebugInformation()) 357 { 358 if (log) 359 log->Printf ("Stepping out of frame with no debug info"); 360 361 should_step_out = true; 362 } 363 } 364 365 if (current_plan->GetKind() == eKindStepInRange) 366 { 367 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 368 if (step_in_range_plan->m_step_into_target) 369 { 370 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 371 if (sc.symbol != NULL) 372 { 373 // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. 374 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) 375 { 376 should_step_out = false; 377 } 378 else 379 { 380 const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); 381 const char *function_name = sc.GetFunctionName().AsCString(); 382 383 if (function_name == NULL) 384 should_step_out = true; 385 else if (strstr (function_name, target_name) == NULL) 386 should_step_out = true; 387 } 388 if (log && should_step_out) 389 log->Printf("Stepping out of frame %s which did not match step into target %s.", 390 sc.GetFunctionName().AsCString(), 391 step_in_range_plan->m_step_into_target.AsCString()); 392 } 393 } 394 395 if (!should_step_out) 396 { 397 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 398 // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria. 399 should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria (); 400 } 401 } 402 403 404 if (should_step_out) 405 { 406 // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions. 407 // We really should have all plans take the tri-state for "stop others" so we can do the right 408 // thing. For now let's be safe and always run others when we are likely to run arbitrary code. 409 const bool stop_others = false; 410 return current_plan->GetThread().QueueThreadPlanForStepOut (false, 411 NULL, 412 true, 413 stop_others, 414 eVoteNo, 415 eVoteNoOpinion, 416 0); // Frame index 417 } 418 419 return ThreadPlanSP(); 420 } 421 422 bool 423 ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr) 424 { 425 // We always explain a stop. Either we've just done a single step, in which 426 // case we'll do our ordinary processing, or we stopped for some 427 // reason that isn't handled by our sub-plans, in which case we want to just stop right 428 // away. 429 // In general, we don't want to mark the plan as complete for unexplained stops. 430 // For instance, if you step in to some code with no debug info, so you step out 431 // and in the course of that hit a breakpoint, then you want to stop & show the user 432 // the breakpoint, but not unship the step in plan, since you still may want to complete that 433 // plan when you continue. This is particularly true when doing "step in to target function." 434 // stepping. 435 // 436 // The only variation is that if we are doing "step by running to next branch" in which case 437 // if we hit our branch breakpoint we don't set the plan to complete. 438 439 bool return_value; 440 441 if (m_virtual_step) 442 { 443 return_value = true; 444 } 445 else 446 { 447 StopInfoSP stop_info_sp = GetPrivateStopInfo (); 448 if (stop_info_sp) 449 { 450 StopReason reason = stop_info_sp->GetStopReason(); 451 452 switch (reason) 453 { 454 case eStopReasonBreakpoint: 455 if (NextRangeBreakpointExplainsStop(stop_info_sp)) 456 { 457 return_value = true; 458 break; 459 } 460 case eStopReasonWatchpoint: 461 case eStopReasonSignal: 462 case eStopReasonException: 463 case eStopReasonExec: 464 case eStopReasonThreadExiting: 465 { 466 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 467 if (log) 468 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 469 } 470 return_value = false; 471 break; 472 default: 473 return_value = true; 474 break; 475 } 476 } 477 else 478 return_value = true; 479 } 480 481 return return_value; 482 } 483 484 bool 485 ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan) 486 { 487 if (resume_state == eStateStepping && current_plan) 488 { 489 // See if we are about to step over a virtual inlined call. 490 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 491 if (step_without_resume) 492 { 493 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 494 if (log) 495 log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d", 496 m_thread.GetCurrentInlinedDepth()); 497 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 498 499 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 500 // the whole rest of the world would have to handle that stop reason. 501 m_virtual_step = true; 502 } 503 return !step_without_resume; 504 } 505 return true; 506 } 507 508 bool 509 ThreadPlanStepInRange::IsVirtualStep() 510 { 511 return m_virtual_step; 512 } 513