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