1 //===-- ThreadPlanStepRange.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/ThreadPlanStepRange.h" 15 #include "lldb/Breakpoint/BreakpointLocation.h" 16 #include "lldb/Breakpoint/BreakpointSite.h" 17 #include "lldb/Core/Disassembler.h" 18 #include "lldb/Core/Log.h" 19 #include "lldb/Core/Stream.h" 20 #include "lldb/Symbol/Function.h" 21 #include "lldb/Symbol/Symbol.h" 22 #include "lldb/Target/ExecutionContext.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/RegisterContext.h" 25 #include "lldb/Target/StopInfo.h" 26 #include "lldb/Target/Target.h" 27 #include "lldb/Target/Thread.h" 28 #include "lldb/Target/ThreadPlanRunToAddress.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 //---------------------------------------------------------------------- 34 // ThreadPlanStepRange: Step through a stack range, either stepping over or into 35 // based on the value of \a type. 36 //---------------------------------------------------------------------- 37 38 ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, 39 const char *name, 40 Thread &thread, 41 const AddressRange &range, 42 const SymbolContext &addr_context, 43 lldb::RunMode stop_others, 44 bool given_ranges_only) : 45 ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 46 m_addr_context (addr_context), 47 m_address_ranges (), 48 m_stop_others (stop_others), 49 m_stack_id (), 50 m_parent_stack_id(), 51 m_no_more_plans (false), 52 m_first_run_event (true), 53 m_use_fast_step(false), 54 m_given_ranges_only (given_ranges_only) 55 { 56 m_use_fast_step = GetTarget().GetUseFastStepping(); 57 AddRange(range); 58 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 59 StackFrameSP parent_stack = m_thread.GetStackFrameAtIndex(1); 60 if (parent_stack) 61 m_parent_stack_id = parent_stack->GetStackID(); 62 } 63 64 ThreadPlanStepRange::~ThreadPlanStepRange () 65 { 66 ClearNextBranchBreakpoint(); 67 68 size_t num_instruction_ranges = m_instruction_ranges.size(); 69 70 // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. 71 // I'll fix that but for now, just clear the list and it will go away nicely. 72 for (size_t i = 0; i < num_instruction_ranges; i++) 73 { 74 if (m_instruction_ranges[i]) 75 m_instruction_ranges[i]->GetInstructionList().Clear(); 76 } 77 } 78 79 void 80 ThreadPlanStepRange::DidPush () 81 { 82 // See if we can find a "next range" breakpoint: 83 SetNextBranchBreakpoint(); 84 } 85 86 bool 87 ThreadPlanStepRange::ValidatePlan (Stream *error) 88 { 89 return true; 90 } 91 92 Vote 93 ThreadPlanStepRange::ShouldReportStop (Event *event_ptr) 94 { 95 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 96 97 const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 98 if (log) 99 log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote); 100 return vote; 101 } 102 103 void 104 ThreadPlanStepRange::AddRange(const AddressRange &new_range) 105 { 106 // For now I'm just adding the ranges. At some point we may want to 107 // condense the ranges if they overlap, though I don't think it is likely 108 // to be very important. 109 m_address_ranges.push_back (new_range); 110 111 // Fill the slot for this address range with an empty DisassemblerSP in the instruction ranges. I want the 112 // indices to match, but I don't want to do the work to disassemble this range if I don't step into it. 113 m_instruction_ranges.push_back (DisassemblerSP()); 114 } 115 116 void 117 ThreadPlanStepRange::DumpRanges(Stream *s) 118 { 119 size_t num_ranges = m_address_ranges.size(); 120 if (num_ranges == 1) 121 { 122 m_address_ranges[0].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress); 123 } 124 else 125 { 126 for (size_t i = 0; i < num_ranges; i++) 127 { 128 s->Printf(" %" PRIu64 ": ", uint64_t(i)); 129 m_address_ranges[i].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress); 130 } 131 } 132 } 133 134 bool 135 ThreadPlanStepRange::InRange () 136 { 137 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 138 bool ret_value = false; 139 140 lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 141 142 size_t num_ranges = m_address_ranges.size(); 143 for (size_t i = 0; i < num_ranges; i++) 144 { 145 ret_value = m_address_ranges[i].ContainsLoadAddress(pc_load_addr, m_thread.CalculateTarget().get()); 146 if (ret_value) 147 break; 148 } 149 150 if (!ret_value && !m_given_ranges_only) 151 { 152 // See if we've just stepped to another part of the same line number... 153 StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 154 155 SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 156 if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 157 { 158 if (m_addr_context.line_entry.file == new_context.line_entry.file) 159 { 160 if (m_addr_context.line_entry.line == new_context.line_entry.line) 161 { 162 m_addr_context = new_context; 163 AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange()); 164 ret_value = true; 165 if (log) 166 { 167 StreamString s; 168 m_addr_context.line_entry.Dump (&s, 169 m_thread.CalculateTarget().get(), 170 true, 171 Address::DumpStyleLoadAddress, 172 Address::DumpStyleLoadAddress, 173 true); 174 175 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 176 } 177 } 178 else if (new_context.line_entry.line == 0) 179 { 180 new_context.line_entry.line = m_addr_context.line_entry.line; 181 m_addr_context = new_context; 182 AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange()); 183 ret_value = true; 184 if (log) 185 { 186 StreamString s; 187 m_addr_context.line_entry.Dump (&s, 188 m_thread.CalculateTarget().get(), 189 true, 190 Address::DumpStyleLoadAddress, 191 Address::DumpStyleLoadAddress, 192 true); 193 194 log->Printf ("Step range plan stepped to a range at linenumber 0 stepping through that range: %s", s.GetData()); 195 } 196 } 197 else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get()) 198 != pc_load_addr) 199 { 200 // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another 201 // line. So far I mostly see this due to bugs in the debug information. 202 // But we probably don't want to be in the middle of a line range, so in that case reset the stepping 203 // range to the line we've stepped into the middle of and continue. 204 m_addr_context = new_context; 205 m_address_ranges.clear(); 206 AddRange(m_addr_context.line_entry.range); 207 ret_value = true; 208 if (log) 209 { 210 StreamString s; 211 m_addr_context.line_entry.Dump (&s, 212 m_thread.CalculateTarget().get(), 213 true, 214 Address::DumpStyleLoadAddress, 215 Address::DumpStyleLoadAddress, 216 true); 217 218 log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.", 219 new_context.line_entry.line, 220 s.GetData()); 221 } 222 } 223 } 224 } 225 } 226 227 if (!ret_value && log) 228 log->Printf ("Step range plan out of range to 0x%" PRIx64, pc_load_addr); 229 230 return ret_value; 231 } 232 233 bool 234 ThreadPlanStepRange::InSymbol() 235 { 236 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 237 if (m_addr_context.function != nullptr) 238 { 239 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 240 } 241 else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) 242 { 243 AddressRange range(m_addr_context.symbol->GetAddressRef(), m_addr_context.symbol->GetByteSize()); 244 return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 245 } 246 return false; 247 } 248 249 // FIXME: This should also handle inlining if we aren't going to do inlining in the 250 // main stack. 251 // 252 // Ideally we should remember the whole stack frame list, and then compare that 253 // to the current list. 254 255 lldb::FrameComparison 256 ThreadPlanStepRange::CompareCurrentFrameToStartFrame() 257 { 258 FrameComparison frame_order; 259 260 StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 261 262 if (cur_frame_id == m_stack_id) 263 { 264 frame_order = eFrameCompareEqual; 265 } 266 else if (cur_frame_id < m_stack_id) 267 { 268 frame_order = eFrameCompareYounger; 269 } 270 else 271 { 272 StackFrameSP cur_parent_frame = m_thread.GetStackFrameAtIndex(1); 273 StackID cur_parent_id; 274 if (cur_parent_frame) 275 cur_parent_id = cur_parent_frame->GetStackID(); 276 if (m_parent_stack_id.IsValid() 277 && cur_parent_id.IsValid() 278 && m_parent_stack_id == cur_parent_id) 279 frame_order = eFrameCompareSameParent; 280 else 281 frame_order = eFrameCompareOlder; 282 } 283 return frame_order; 284 } 285 286 bool 287 ThreadPlanStepRange::StopOthers () 288 { 289 return (m_stop_others == lldb::eOnlyThisThread || m_stop_others == lldb::eOnlyDuringStepping); 290 } 291 292 InstructionList * 293 ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset) 294 { 295 size_t num_ranges = m_address_ranges.size(); 296 for (size_t i = 0; i < num_ranges; i++) 297 { 298 if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) 299 { 300 // Some joker added a zero size range to the stepping range... 301 if (m_address_ranges[i].GetByteSize() == 0) 302 return nullptr; 303 304 if (!m_instruction_ranges[i]) 305 { 306 //Disassemble the address range given: 307 ExecutionContext exe_ctx (m_thread.GetProcess()); 308 const char *plugin_name = nullptr; 309 const char *flavor = nullptr; 310 const bool prefer_file_cache = true; 311 m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), 312 plugin_name, 313 flavor, 314 exe_ctx, 315 m_address_ranges[i], 316 prefer_file_cache); 317 } 318 if (!m_instruction_ranges[i]) 319 return nullptr; 320 else 321 { 322 // Find where we are in the instruction list as well. If we aren't at an instruction, 323 // return nullptr. In this case, we're probably lost, and shouldn't try to do anything fancy. 324 325 insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 326 if (insn_offset == UINT32_MAX) 327 return nullptr; 328 else 329 { 330 range_index = i; 331 return &m_instruction_ranges[i]->GetInstructionList(); 332 } 333 } 334 } 335 } 336 return nullptr; 337 } 338 339 void 340 ThreadPlanStepRange::ClearNextBranchBreakpoint() 341 { 342 if (m_next_branch_bp_sp) 343 { 344 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 345 if (log) 346 log->Printf ("Removing next branch breakpoint: %d.", m_next_branch_bp_sp->GetID()); 347 GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); 348 m_next_branch_bp_sp.reset(); 349 } 350 } 351 352 bool 353 ThreadPlanStepRange::SetNextBranchBreakpoint () 354 { 355 if (m_next_branch_bp_sp) 356 return true; 357 358 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 359 // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction 360 // single stepping. 361 if (!m_use_fast_step) 362 return false; 363 364 lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 365 // Find the current address in our address ranges, and fetch the disassembly if we haven't already: 366 size_t pc_index; 367 size_t range_index; 368 InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); 369 if (instructions == nullptr) 370 return false; 371 else 372 { 373 Target &target = GetThread().GetProcess()->GetTarget(); 374 uint32_t branch_index; 375 branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index, target); 376 377 Address run_to_address; 378 379 // If we didn't find a branch, run to the end of the range. 380 if (branch_index == UINT32_MAX) 381 { 382 uint32_t last_index = instructions->GetSize() - 1; 383 if (last_index - pc_index > 1) 384 { 385 InstructionSP last_inst = instructions->GetInstructionAtIndex(last_index); 386 size_t last_inst_size = last_inst->GetOpcode().GetByteSize(); 387 run_to_address = last_inst->GetAddress(); 388 run_to_address.Slide(last_inst_size); 389 } 390 } 391 else if (branch_index - pc_index > 1) 392 { 393 run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 394 } 395 396 if (run_to_address.IsValid()) 397 { 398 const bool is_internal = true; 399 m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal, false); 400 if (m_next_branch_bp_sp) 401 { 402 if (log) 403 { 404 lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID; 405 BreakpointLocationSP bp_loc = m_next_branch_bp_sp->GetLocationAtIndex(0); 406 if (bp_loc) 407 { 408 BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite(); 409 if (bp_site) 410 { 411 bp_site_id = bp_site->GetID(); 412 } 413 } 414 log->Printf ("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting breakpoint %d (site %d) to run to address 0x%" PRIx64, 415 m_next_branch_bp_sp->GetID(), 416 bp_site_id, 417 run_to_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget())); 418 } 419 m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 420 m_next_branch_bp_sp->SetBreakpointKind ("next-branch-location"); 421 return true; 422 } 423 else 424 return false; 425 } 426 } 427 return false; 428 } 429 430 bool 431 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) 432 { 433 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 434 if (!m_next_branch_bp_sp) 435 return false; 436 437 break_id_t bp_site_id = stop_info_sp->GetValue(); 438 BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 439 if (!bp_site_sp) 440 return false; 441 else if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) 442 return false; 443 else 444 { 445 // If we've hit the next branch breakpoint, then clear it. 446 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 447 bool explains_stop = true; 448 // If all the owners are internal, then we are probably just stepping over this range from multiple threads, 449 // or multiple frames, so we want to continue. If one is not internal, then we should not explain the stop, 450 // and let the user breakpoint handle the stop. 451 for (size_t i = 0; i < num_owners; i++) 452 { 453 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) 454 { 455 explains_stop = false; 456 break; 457 } 458 } 459 if (log) 460 log->Printf ("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit next range breakpoint which has %" PRIu64 " owners - explains stop: %u.", 461 (uint64_t)num_owners, 462 explains_stop); 463 ClearNextBranchBreakpoint(); 464 return explains_stop; 465 } 466 } 467 468 bool 469 ThreadPlanStepRange::WillStop () 470 { 471 return true; 472 } 473 474 StateType 475 ThreadPlanStepRange::GetPlanRunState () 476 { 477 if (m_next_branch_bp_sp) 478 return eStateRunning; 479 else 480 return eStateStepping; 481 } 482 483 bool 484 ThreadPlanStepRange::MischiefManaged () 485 { 486 // If we have pushed some plans between ShouldStop & MischiefManaged, then we're not done... 487 // I do this check first because we might have stepped somewhere that will fool InRange into 488 // thinking it needs to step past the end of that line. This happens, for instance, when stepping 489 // over inlined code that is in the middle of the current line. 490 491 if (!m_no_more_plans) 492 return false; 493 494 bool done = true; 495 if (!IsPlanComplete()) 496 { 497 if (InRange()) 498 { 499 done = false; 500 } 501 else 502 { 503 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 504 done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true; 505 } 506 } 507 508 if (done) 509 { 510 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 511 if (log) 512 log->Printf("Completed step through range plan."); 513 ClearNextBranchBreakpoint(); 514 ThreadPlan::MischiefManaged (); 515 return true; 516 } 517 else 518 { 519 return false; 520 } 521 } 522 523 bool 524 ThreadPlanStepRange::IsPlanStale () 525 { 526 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 527 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 528 529 if (frame_order == eFrameCompareOlder) 530 { 531 if (log) 532 { 533 log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out."); 534 } 535 return true; 536 } 537 else if (frame_order == eFrameCompareEqual && InSymbol()) 538 { 539 // If we are not in a place we should step through, we've gotten stale. 540 // One tricky bit here is that some stubs don't push a frame, so we should. 541 // check that we are in the same symbol. 542 if (!InRange()) 543 { 544 return true; 545 } 546 } 547 return false; 548 } 549