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