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 FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid()); 283 size_t num_libraries = libraries_to_avoid.GetSize(); 284 bool libraries_say_avoid = false; 285 SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); 286 FileSpec frame_library(sc.module_sp->GetFileSpec()); 287 288 if (frame_library) 289 { 290 for (size_t i = 0; i < num_libraries; i++) 291 { 292 const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); 293 if (FileSpec::Equal (file_spec, frame_library, false)) 294 { 295 libraries_say_avoid = true; 296 break; 297 } 298 } 299 } 300 if (libraries_say_avoid) 301 return true; 302 303 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 304 if (avoid_regexp_to_use == NULL) 305 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 306 307 if (avoid_regexp_to_use != NULL) 308 { 309 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 310 if (sc.symbol != NULL) 311 { 312 const char *frame_function_name = sc.GetFunctionName().GetCString(); 313 if (frame_function_name) 314 { 315 size_t num_matches = 0; 316 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 317 if (log) 318 num_matches = 1; 319 320 RegularExpression::Match regex_match(num_matches); 321 322 bool return_value = avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); 323 if (return_value) 324 { 325 if (log) 326 { 327 std::string match; 328 regex_match.GetMatchAtIndex(frame_function_name,0, match); 329 log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".", 330 frame_function_name, 331 avoid_regexp_to_use->GetText(), 332 match.c_str()); 333 } 334 335 } 336 return return_value; 337 } 338 } 339 } 340 return false; 341 } 342 343 ThreadPlanSP 344 ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton) 345 { 346 bool should_step_out = false; 347 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 348 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 349 350 if (flags.Test(eAvoidNoDebug)) 351 { 352 if (!frame->HasDebugInformation()) 353 { 354 if (log) 355 log->Printf ("Stepping out of frame with no debug info"); 356 357 should_step_out = true; 358 } 359 } 360 361 if (current_plan->GetKind() == eKindStepInRange) 362 { 363 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 364 if (step_in_range_plan->m_step_into_target) 365 { 366 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 367 if (sc.symbol != NULL) 368 { 369 // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. 370 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) 371 { 372 should_step_out = false; 373 } 374 else 375 { 376 const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); 377 const char *function_name = sc.GetFunctionName().AsCString(); 378 379 if (function_name == NULL) 380 should_step_out = true; 381 else if (strstr (function_name, target_name) == NULL) 382 should_step_out = true; 383 } 384 if (log && should_step_out) 385 log->Printf("Stepping out of frame %s which did not match step into target %s.", 386 sc.GetFunctionName().AsCString(), 387 step_in_range_plan->m_step_into_target.AsCString()); 388 } 389 } 390 391 if (!should_step_out) 392 { 393 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 394 // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria. 395 should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria (); 396 } 397 } 398 399 400 if (should_step_out) 401 { 402 // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions. 403 // We really should have all plans take the tri-state for "stop others" so we can do the right 404 // thing. For now let's be safe and always run others when we are likely to run arbitrary code. 405 const bool stop_others = false; 406 return current_plan->GetThread().QueueThreadPlanForStepOut (false, 407 NULL, 408 true, 409 stop_others, 410 eVoteNo, 411 eVoteNoOpinion, 412 0); // Frame index 413 } 414 415 return ThreadPlanSP(); 416 } 417 418 bool 419 ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr) 420 { 421 // We always explain a stop. Either we've just done a single step, in which 422 // case we'll do our ordinary processing, or we stopped for some 423 // reason that isn't handled by our sub-plans, in which case we want to just stop right 424 // away. 425 // In general, we don't want to mark the plan as complete for unexplained stops. 426 // For instance, if you step in to some code with no debug info, so you step out 427 // and in the course of that hit a breakpoint, then you want to stop & show the user 428 // the breakpoint, but not unship the step in plan, since you still may want to complete that 429 // plan when you continue. This is particularly true when doing "step in to target function." 430 // stepping. 431 // 432 // The only variation is that if we are doing "step by running to next branch" in which case 433 // if we hit our branch breakpoint we don't set the plan to complete. 434 435 bool return_value; 436 437 if (m_virtual_step) 438 { 439 return_value = true; 440 } 441 else 442 { 443 StopInfoSP stop_info_sp = GetPrivateStopInfo (); 444 if (stop_info_sp) 445 { 446 StopReason reason = stop_info_sp->GetStopReason(); 447 448 switch (reason) 449 { 450 case eStopReasonBreakpoint: 451 if (NextRangeBreakpointExplainsStop(stop_info_sp)) 452 { 453 return_value = true; 454 break; 455 } 456 case eStopReasonWatchpoint: 457 case eStopReasonSignal: 458 case eStopReasonException: 459 case eStopReasonExec: 460 case eStopReasonThreadExiting: 461 { 462 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 463 if (log) 464 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 465 } 466 return_value = false; 467 break; 468 default: 469 return_value = true; 470 break; 471 } 472 } 473 else 474 return_value = true; 475 } 476 477 return return_value; 478 } 479 480 bool 481 ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan) 482 { 483 if (resume_state == eStateStepping && current_plan) 484 { 485 // See if we are about to step over a virtual inlined call. 486 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 487 if (step_without_resume) 488 { 489 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 490 if (log) 491 log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d", 492 m_thread.GetCurrentInlinedDepth()); 493 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 494 495 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 496 // the whole rest of the world would have to handle that stop reason. 497 m_virtual_step = true; 498 } 499 return !step_without_resume; 500 } 501 return true; 502 } 503 504 bool 505 ThreadPlanStepInRange::IsVirtualStep() 506 { 507 return m_virtual_step; 508 } 509