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