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