130fdc8d8SChris Lattner //===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 10e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanStepRange.h" 110c61dee1SJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h" 120c61dee1SJim Ingham #include "lldb/Breakpoint/BreakpointSite.h" 13564d8bc2SJim Ingham #include "lldb/Core/Disassembler.h" 1430fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 1530fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 16564d8bc2SJim Ingham #include "lldb/Target/ExecutionContext.h" 17f4b47e15SGreg Clayton #include "lldb/Target/Process.h" 18f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h" 19f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h" 20564d8bc2SJim Ingham #include "lldb/Target/Target.h" 21f4b47e15SGreg Clayton #include "lldb/Target/Thread.h" 22564d8bc2SJim Ingham #include "lldb/Target/ThreadPlanRunToAddress.h" 236f9e6901SZachary Turner #include "lldb/Utility/Log.h" 24bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner using namespace lldb; 2730fdc8d8SChris Lattner using namespace lldb_private; 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 3005097246SAdrian Prantl // ThreadPlanStepRange: Step through a stack range, either stepping over or 3105097246SAdrian Prantl // into based on the value of \a type. 3230fdc8d8SChris Lattner //---------------------------------------------------------------------- 3330fdc8d8SChris Lattner 34b9c1b51eSKate Stone ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name, 35242e0ad7SJim Ingham Thread &thread, 36242e0ad7SJim Ingham const AddressRange &range, 37242e0ad7SJim Ingham const SymbolContext &addr_context, 382bdbfd50SJim Ingham lldb::RunMode stop_others, 39b9c1b51eSKate Stone bool given_ranges_only) 40b9c1b51eSKate Stone : ThreadPlan(kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 41b9c1b51eSKate Stone m_addr_context(addr_context), m_address_ranges(), 42b9c1b51eSKate Stone m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(), 43b9c1b51eSKate Stone m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false), 44b9c1b51eSKate Stone m_given_ranges_only(given_ranges_only) { 4517d023f6SJim Ingham m_use_fast_step = GetTarget().GetUseFastStepping(); 46c4c9fedcSJim Ingham AddRange(range); 4730fdc8d8SChris Lattner m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 4876447851SJim Ingham StackFrameSP parent_stack = m_thread.GetStackFrameAtIndex(1); 4976447851SJim Ingham if (parent_stack) 5076447851SJim Ingham m_parent_stack_id = parent_stack->GetStackID(); 5130fdc8d8SChris Lattner } 5230fdc8d8SChris Lattner 53b9c1b51eSKate Stone ThreadPlanStepRange::~ThreadPlanStepRange() { ClearNextBranchBreakpoint(); } 54564d8bc2SJim Ingham 55b9c1b51eSKate Stone void ThreadPlanStepRange::DidPush() { 56564d8bc2SJim Ingham // See if we can find a "next range" breakpoint: 57564d8bc2SJim Ingham SetNextBranchBreakpoint(); 5830fdc8d8SChris Lattner } 5930fdc8d8SChris Lattner 60*e103ae92SJonas Devlieghere bool ThreadPlanStepRange::ValidatePlan(Stream *error) { 61*e103ae92SJonas Devlieghere if (m_could_not_resolve_hw_bp) { 62*e103ae92SJonas Devlieghere if (error) 63*e103ae92SJonas Devlieghere error->PutCString( 64*e103ae92SJonas Devlieghere "Could not create hardware breakpoint for thread plan."); 65*e103ae92SJonas Devlieghere return false; 66*e103ae92SJonas Devlieghere } 67*e103ae92SJonas Devlieghere return true; 68*e103ae92SJonas Devlieghere } 6930fdc8d8SChris Lattner 70b9c1b51eSKate Stone Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) { 715160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 722cad65a5SGreg Clayton 732cad65a5SGreg Clayton const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 742cad65a5SGreg Clayton if (log) 75b9c1b51eSKate Stone log->Printf("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", 76b9c1b51eSKate Stone vote); 772cad65a5SGreg Clayton return vote; 7830fdc8d8SChris Lattner } 7930fdc8d8SChris Lattner 80b9c1b51eSKate Stone void ThreadPlanStepRange::AddRange(const AddressRange &new_range) { 8105097246SAdrian Prantl // For now I'm just adding the ranges. At some point we may want to condense 8205097246SAdrian Prantl // the ranges if they overlap, though I don't think it is likely to be very 8305097246SAdrian Prantl // important. 84c4c9fedcSJim Ingham m_address_ranges.push_back(new_range); 8556d40428SJim Ingham 86b9c1b51eSKate Stone // Fill the slot for this address range with an empty DisassemblerSP in the 8705097246SAdrian Prantl // instruction ranges. I want the indices to match, but I don't want to do 8805097246SAdrian Prantl // the work to disassemble this range if I don't step into it. 89564d8bc2SJim Ingham m_instruction_ranges.push_back(DisassemblerSP()); 90c4c9fedcSJim Ingham } 91c4c9fedcSJim Ingham 92b9c1b51eSKate Stone void ThreadPlanStepRange::DumpRanges(Stream *s) { 93c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 94b9c1b51eSKate Stone if (num_ranges == 1) { 95b9c1b51eSKate Stone m_address_ranges[0].Dump(s, m_thread.CalculateTarget().get(), 96b9c1b51eSKate Stone Address::DumpStyleLoadAddress); 97b9c1b51eSKate Stone } else { 98b9c1b51eSKate Stone for (size_t i = 0; i < num_ranges; i++) { 998c0970feSPavel Labath s->Printf(" %" PRIu64 ": ", uint64_t(i)); 100b9c1b51eSKate Stone m_address_ranges[i].Dump(s, m_thread.CalculateTarget().get(), 101b9c1b51eSKate Stone Address::DumpStyleLoadAddress); 102c4c9fedcSJim Ingham } 103c4c9fedcSJim Ingham } 104c4c9fedcSJim Ingham } 105c4c9fedcSJim Ingham 106b9c1b51eSKate Stone bool ThreadPlanStepRange::InRange() { 1075160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 10830fdc8d8SChris Lattner bool ret_value = false; 10930fdc8d8SChris Lattner 11030fdc8d8SChris Lattner lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 11130fdc8d8SChris Lattner 112c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 113b9c1b51eSKate Stone for (size_t i = 0; i < num_ranges; i++) { 114b9c1b51eSKate Stone ret_value = m_address_ranges[i].ContainsLoadAddress( 115b9c1b51eSKate Stone pc_load_addr, m_thread.CalculateTarget().get()); 116c4c9fedcSJim Ingham if (ret_value) 117c4c9fedcSJim Ingham break; 118c4c9fedcSJim Ingham } 11930fdc8d8SChris Lattner 120b9c1b51eSKate Stone if (!ret_value && !m_given_ranges_only) { 12130fdc8d8SChris Lattner // See if we've just stepped to another part of the same line number... 122b57e4a1bSJason Molenda StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 12330fdc8d8SChris Lattner 124b9c1b51eSKate Stone SymbolContext new_context( 125b9c1b51eSKate Stone frame->GetSymbolContext(eSymbolContextEverything)); 126b9c1b51eSKate Stone if (m_addr_context.line_entry.IsValid() && 127b9c1b51eSKate Stone new_context.line_entry.IsValid()) { 128b9c1b51eSKate Stone if (m_addr_context.line_entry.original_file == 129b9c1b51eSKate Stone new_context.line_entry.original_file) { 130b9c1b51eSKate Stone if (m_addr_context.line_entry.line == new_context.line_entry.line) { 13130fdc8d8SChris Lattner m_addr_context = new_context; 132b9c1b51eSKate Stone AddRange( 133b9c1b51eSKate Stone m_addr_context.line_entry.GetSameLineContiguousAddressRange()); 13430fdc8d8SChris Lattner ret_value = true; 135b9c1b51eSKate Stone if (log) { 13630fdc8d8SChris Lattner StreamString s; 137b9c1b51eSKate Stone m_addr_context.line_entry.Dump(&s, m_thread.CalculateTarget().get(), 138b9c1b51eSKate Stone true, Address::DumpStyleLoadAddress, 139b9c1b51eSKate Stone Address::DumpStyleLoadAddress, true); 14030fdc8d8SChris Lattner 141b9c1b51eSKate Stone log->Printf( 142b9c1b51eSKate Stone "Step range plan stepped to another range of same line: %s", 143b9c1b51eSKate Stone s.GetData()); 14430fdc8d8SChris Lattner } 145b9c1b51eSKate Stone } else if (new_context.line_entry.line == 0) { 1462b89a531SJim Ingham new_context.line_entry.line = m_addr_context.line_entry.line; 1472b89a531SJim Ingham m_addr_context = new_context; 148b9c1b51eSKate Stone AddRange( 149b9c1b51eSKate Stone m_addr_context.line_entry.GetSameLineContiguousAddressRange()); 1502b89a531SJim Ingham ret_value = true; 151b9c1b51eSKate Stone if (log) { 1522b89a531SJim Ingham StreamString s; 153b9c1b51eSKate Stone m_addr_context.line_entry.Dump(&s, m_thread.CalculateTarget().get(), 154b9c1b51eSKate Stone true, Address::DumpStyleLoadAddress, 155b9c1b51eSKate Stone Address::DumpStyleLoadAddress, true); 1562b89a531SJim Ingham 157b9c1b51eSKate Stone log->Printf("Step range plan stepped to a range at linenumber 0 " 158b9c1b51eSKate Stone "stepping through that range: %s", 159b9c1b51eSKate Stone s.GetData()); 1602b89a531SJim Ingham } 161b9c1b51eSKate Stone } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress( 162b9c1b51eSKate Stone m_thread.CalculateTarget().get()) != pc_load_addr) { 163b9c1b51eSKate Stone // Another thing that sometimes happens here is that we step out of 16405097246SAdrian Prantl // one line into the MIDDLE of another line. So far I mostly see 16505097246SAdrian Prantl // this due to bugs in the debug information. But we probably don't 16605097246SAdrian Prantl // want to be in the middle of a line range, so in that case reset 16705097246SAdrian Prantl // the stepping range to the line we've stepped into the middle of 16805097246SAdrian Prantl // and continue. 169843bfb2cSJim Ingham m_addr_context = new_context; 170c4c9fedcSJim Ingham m_address_ranges.clear(); 171c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 172843bfb2cSJim Ingham ret_value = true; 173b9c1b51eSKate Stone if (log) { 174843bfb2cSJim Ingham StreamString s; 175b9c1b51eSKate Stone m_addr_context.line_entry.Dump(&s, m_thread.CalculateTarget().get(), 176b9c1b51eSKate Stone true, Address::DumpStyleLoadAddress, 177b9c1b51eSKate Stone Address::DumpStyleLoadAddress, true); 178843bfb2cSJim Ingham 179b9c1b51eSKate Stone log->Printf("Step range plan stepped to the middle of new " 180b9c1b51eSKate Stone "line(%d): %s, continuing to clear this line.", 181b9c1b51eSKate Stone new_context.line_entry.line, s.GetData()); 182843bfb2cSJim Ingham } 183843bfb2cSJim Ingham } 184843bfb2cSJim Ingham } 18530fdc8d8SChris Lattner } 18630fdc8d8SChris Lattner } 18730fdc8d8SChris Lattner 18830fdc8d8SChris Lattner if (!ret_value && log) 189d01b2953SDaniel Malea log->Printf("Step range plan out of range to 0x%" PRIx64, pc_load_addr); 19030fdc8d8SChris Lattner 19130fdc8d8SChris Lattner return ret_value; 19230fdc8d8SChris Lattner } 19330fdc8d8SChris Lattner 194b9c1b51eSKate Stone bool ThreadPlanStepRange::InSymbol() { 19530fdc8d8SChris Lattner lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 196b9c1b51eSKate Stone if (m_addr_context.function != nullptr) { 197b9c1b51eSKate Stone return m_addr_context.function->GetAddressRange().ContainsLoadAddress( 198b9c1b51eSKate Stone cur_pc, m_thread.CalculateTarget().get()); 199b9c1b51eSKate Stone } else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) { 200b9c1b51eSKate Stone AddressRange range(m_addr_context.symbol->GetAddressRef(), 201b9c1b51eSKate Stone m_addr_context.symbol->GetByteSize()); 202e7612134SGreg Clayton return range.ContainsLoadAddress(cur_pc, m_thread.CalculateTarget().get()); 20330fdc8d8SChris Lattner } 20430fdc8d8SChris Lattner return false; 20530fdc8d8SChris Lattner } 20630fdc8d8SChris Lattner 207b9c1b51eSKate Stone // FIXME: This should also handle inlining if we aren't going to do inlining in 208b9c1b51eSKate Stone // the 20930fdc8d8SChris Lattner // main stack. 21030fdc8d8SChris Lattner // 21130fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that 21230fdc8d8SChris Lattner // to the current list. 21330fdc8d8SChris Lattner 214b9c1b51eSKate Stone lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() { 215b5c0d1ccSJim Ingham FrameComparison frame_order; 2167ce490c6SJim Ingham 217b5c0d1ccSJim Ingham StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 2187ce490c6SJim Ingham 219b9c1b51eSKate Stone if (cur_frame_id == m_stack_id) { 220b5c0d1ccSJim Ingham frame_order = eFrameCompareEqual; 221b9c1b51eSKate Stone } else if (cur_frame_id < m_stack_id) { 222b5c0d1ccSJim Ingham frame_order = eFrameCompareYounger; 223b9c1b51eSKate Stone } else { 22476447851SJim Ingham StackFrameSP cur_parent_frame = m_thread.GetStackFrameAtIndex(1); 22576447851SJim Ingham StackID cur_parent_id; 22676447851SJim Ingham if (cur_parent_frame) 22776447851SJim Ingham cur_parent_id = cur_parent_frame->GetStackID(); 228b9c1b51eSKate Stone if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() && 229b9c1b51eSKate Stone m_parent_stack_id == cur_parent_id) 230862d1bbdSJim Ingham frame_order = eFrameCompareSameParent; 231862d1bbdSJim Ingham else 232b5c0d1ccSJim Ingham frame_order = eFrameCompareOlder; 23330fdc8d8SChris Lattner } 234b5c0d1ccSJim Ingham return frame_order; 23530fdc8d8SChris Lattner } 23630fdc8d8SChris Lattner 237b9c1b51eSKate Stone bool ThreadPlanStepRange::StopOthers() { 238b9c1b51eSKate Stone return (m_stop_others == lldb::eOnlyThisThread || 239b9c1b51eSKate Stone m_stop_others == lldb::eOnlyDuringStepping); 24030fdc8d8SChris Lattner } 24130fdc8d8SChris Lattner 242b9c1b51eSKate Stone InstructionList *ThreadPlanStepRange::GetInstructionsForAddress( 243b9c1b51eSKate Stone lldb::addr_t addr, size_t &range_index, size_t &insn_offset) { 244564d8bc2SJim Ingham size_t num_ranges = m_address_ranges.size(); 245b9c1b51eSKate Stone for (size_t i = 0; i < num_ranges; i++) { 246b9c1b51eSKate Stone if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) { 247564d8bc2SJim Ingham // Some joker added a zero size range to the stepping range... 248564d8bc2SJim Ingham if (m_address_ranges[i].GetByteSize() == 0) 249e65b2cf2SEugene Zelenko return nullptr; 250564d8bc2SJim Ingham 251b9c1b51eSKate Stone if (!m_instruction_ranges[i]) { 252564d8bc2SJim Ingham // Disassemble the address range given: 253564d8bc2SJim Ingham ExecutionContext exe_ctx(m_thread.GetProcess()); 254e65b2cf2SEugene Zelenko const char *plugin_name = nullptr; 255e65b2cf2SEugene Zelenko const char *flavor = nullptr; 2566b3e6d54SJason Molenda const bool prefer_file_cache = true; 257b9c1b51eSKate Stone m_instruction_ranges[i] = Disassembler::DisassembleRange( 258b9c1b51eSKate Stone GetTarget().GetArchitecture(), plugin_name, flavor, exe_ctx, 259b9c1b51eSKate Stone m_address_ranges[i], prefer_file_cache); 260564d8bc2SJim Ingham } 261564d8bc2SJim Ingham if (!m_instruction_ranges[i]) 262e65b2cf2SEugene Zelenko return nullptr; 263b9c1b51eSKate Stone else { 264b9c1b51eSKate Stone // Find where we are in the instruction list as well. If we aren't at 26505097246SAdrian Prantl // an instruction, return nullptr. In this case, we're probably lost, 26605097246SAdrian Prantl // and shouldn't try to do anything fancy. 267564d8bc2SJim Ingham 268b9c1b51eSKate Stone insn_offset = 269b9c1b51eSKate Stone m_instruction_ranges[i] 270b9c1b51eSKate Stone ->GetInstructionList() 271b9c1b51eSKate Stone .GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 272564d8bc2SJim Ingham if (insn_offset == UINT32_MAX) 273e65b2cf2SEugene Zelenko return nullptr; 274b9c1b51eSKate Stone else { 275564d8bc2SJim Ingham range_index = i; 276564d8bc2SJim Ingham return &m_instruction_ranges[i]->GetInstructionList(); 277564d8bc2SJim Ingham } 278564d8bc2SJim Ingham } 279564d8bc2SJim Ingham } 280564d8bc2SJim Ingham } 281e65b2cf2SEugene Zelenko return nullptr; 282564d8bc2SJim Ingham } 283564d8bc2SJim Ingham 284b9c1b51eSKate Stone void ThreadPlanStepRange::ClearNextBranchBreakpoint() { 285b9c1b51eSKate Stone if (m_next_branch_bp_sp) { 2865160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 2870c61dee1SJim Ingham if (log) 288b9c1b51eSKate Stone log->Printf("Removing next branch breakpoint: %d.", 289b9c1b51eSKate Stone m_next_branch_bp_sp->GetID()); 290564d8bc2SJim Ingham GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID()); 291564d8bc2SJim Ingham m_next_branch_bp_sp.reset(); 292*e103ae92SJonas Devlieghere m_could_not_resolve_hw_bp = false; 293564d8bc2SJim Ingham } 294564d8bc2SJim Ingham } 295564d8bc2SJim Ingham 296b9c1b51eSKate Stone bool ThreadPlanStepRange::SetNextBranchBreakpoint() { 2970c61dee1SJim Ingham if (m_next_branch_bp_sp) 2980c61dee1SJim Ingham return true; 2990c61dee1SJim Ingham 3005160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 301b9c1b51eSKate Stone // Stepping through ranges using breakpoints doesn't work yet, but with this 30205097246SAdrian Prantl // off we fall back to instruction single stepping. 3030c61dee1SJim Ingham if (!m_use_fast_step) 304564d8bc2SJim Ingham return false; 3050c61dee1SJim Ingham 306564d8bc2SJim Ingham lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 307b9c1b51eSKate Stone // Find the current address in our address ranges, and fetch the disassembly 308b9c1b51eSKate Stone // if we haven't already: 309564d8bc2SJim Ingham size_t pc_index; 310564d8bc2SJim Ingham size_t range_index; 311b9c1b51eSKate Stone InstructionList *instructions = 312b9c1b51eSKate Stone GetInstructionsForAddress(cur_addr, range_index, pc_index); 313e65b2cf2SEugene Zelenko if (instructions == nullptr) 314564d8bc2SJim Ingham return false; 315b9c1b51eSKate Stone else { 316e76e7e93STed Woodward Target &target = GetThread().GetProcess()->GetTarget(); 317564d8bc2SJim Ingham uint32_t branch_index; 318b9c1b51eSKate Stone branch_index = 319b9c1b51eSKate Stone instructions->GetIndexOfNextBranchInstruction(pc_index, target); 320564d8bc2SJim Ingham 321564d8bc2SJim Ingham Address run_to_address; 322564d8bc2SJim Ingham 323564d8bc2SJim Ingham // If we didn't find a branch, run to the end of the range. 324b9c1b51eSKate Stone if (branch_index == UINT32_MAX) { 325a3f466b9SJim Ingham uint32_t last_index = instructions->GetSize() - 1; 326b9c1b51eSKate Stone if (last_index - pc_index > 1) { 327b9c1b51eSKate Stone InstructionSP last_inst = 328b9c1b51eSKate Stone instructions->GetInstructionAtIndex(last_index); 329a3f466b9SJim Ingham size_t last_inst_size = last_inst->GetOpcode().GetByteSize(); 330a3f466b9SJim Ingham run_to_address = last_inst->GetAddress(); 331a3f466b9SJim Ingham run_to_address.Slide(last_inst_size); 332a3f466b9SJim Ingham } 333b9c1b51eSKate Stone } else if (branch_index - pc_index > 1) { 334b9c1b51eSKate Stone run_to_address = 335b9c1b51eSKate Stone instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 336564d8bc2SJim Ingham } 3370c61dee1SJim Ingham 338b9c1b51eSKate Stone if (run_to_address.IsValid()) { 339564d8bc2SJim Ingham const bool is_internal = true; 340b9c1b51eSKate Stone m_next_branch_bp_sp = 341b9c1b51eSKate Stone GetTarget().CreateBreakpoint(run_to_address, is_internal, false); 342b9c1b51eSKate Stone if (m_next_branch_bp_sp) { 343*e103ae92SJonas Devlieghere 344*e103ae92SJonas Devlieghere if (m_next_branch_bp_sp->IsHardware() && 345*e103ae92SJonas Devlieghere !m_next_branch_bp_sp->HasResolvedLocations()) 346*e103ae92SJonas Devlieghere m_could_not_resolve_hw_bp = true; 347*e103ae92SJonas Devlieghere 348b9c1b51eSKate Stone if (log) { 3490c61dee1SJim Ingham lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID; 350b9c1b51eSKate Stone BreakpointLocationSP bp_loc = 351b9c1b51eSKate Stone m_next_branch_bp_sp->GetLocationAtIndex(0); 352b9c1b51eSKate Stone if (bp_loc) { 3530c61dee1SJim Ingham BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite(); 354b9c1b51eSKate Stone if (bp_site) { 3550c61dee1SJim Ingham bp_site_id = bp_site->GetID(); 3560c61dee1SJim Ingham } 3570c61dee1SJim Ingham } 358b9c1b51eSKate Stone log->Printf("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting " 359b9c1b51eSKate Stone "breakpoint %d (site %d) to run to address 0x%" PRIx64, 360b9c1b51eSKate Stone m_next_branch_bp_sp->GetID(), bp_site_id, 361b9c1b51eSKate Stone run_to_address.GetLoadAddress( 362b9c1b51eSKate Stone &m_thread.GetProcess()->GetTarget())); 3630c61dee1SJim Ingham } 364*e103ae92SJonas Devlieghere 365564d8bc2SJim Ingham m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 3662995077dSJim Ingham m_next_branch_bp_sp->SetBreakpointKind("next-branch-location"); 367*e103ae92SJonas Devlieghere 3680c61dee1SJim Ingham return true; 369b9c1b51eSKate Stone } else 3702995077dSJim Ingham return false; 371564d8bc2SJim Ingham } 372564d8bc2SJim Ingham } 373564d8bc2SJim Ingham return false; 374564d8bc2SJim Ingham } 375564d8bc2SJim Ingham 376b9c1b51eSKate Stone bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop( 377b9c1b51eSKate Stone lldb::StopInfoSP stop_info_sp) { 3785160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 379564d8bc2SJim Ingham if (!m_next_branch_bp_sp) 380564d8bc2SJim Ingham return false; 381564d8bc2SJim Ingham 382564d8bc2SJim Ingham break_id_t bp_site_id = stop_info_sp->GetValue(); 383b9c1b51eSKate Stone BreakpointSiteSP bp_site_sp = 384b9c1b51eSKate Stone m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 3850c61dee1SJim Ingham if (!bp_site_sp) 3860c61dee1SJim Ingham return false; 3870c61dee1SJim Ingham else if (!bp_site_sp->IsBreakpointAtThisSite(m_next_branch_bp_sp->GetID())) 388564d8bc2SJim Ingham return false; 389b9c1b51eSKate Stone else { 3900c61dee1SJim Ingham // If we've hit the next branch breakpoint, then clear it. 3910c61dee1SJim Ingham size_t num_owners = bp_site_sp->GetNumberOfOwners(); 3920c61dee1SJim Ingham bool explains_stop = true; 393b9c1b51eSKate Stone // If all the owners are internal, then we are probably just stepping over 39405097246SAdrian Prantl // this range from multiple threads, or multiple frames, so we want to 39505097246SAdrian Prantl // continue. If one is not internal, then we should not explain the stop, 3960c61dee1SJim Ingham // and let the user breakpoint handle the stop. 397b9c1b51eSKate Stone for (size_t i = 0; i < num_owners; i++) { 398b9c1b51eSKate Stone if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) { 3990c61dee1SJim Ingham explains_stop = false; 4000c61dee1SJim Ingham break; 4010c61dee1SJim Ingham } 4020c61dee1SJim Ingham } 4030c61dee1SJim Ingham if (log) 404b9c1b51eSKate Stone log->Printf("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit " 405b9c1b51eSKate Stone "next range breakpoint which has %" PRIu64 406b9c1b51eSKate Stone " owners - explains stop: %u.", 407b9c1b51eSKate Stone (uint64_t)num_owners, explains_stop); 4080c61dee1SJim Ingham ClearNextBranchBreakpoint(); 4090c61dee1SJim Ingham return explains_stop; 4100c61dee1SJim Ingham } 411564d8bc2SJim Ingham } 412564d8bc2SJim Ingham 413b9c1b51eSKate Stone bool ThreadPlanStepRange::WillStop() { return true; } 41430fdc8d8SChris Lattner 415b9c1b51eSKate Stone StateType ThreadPlanStepRange::GetPlanRunState() { 416564d8bc2SJim Ingham if (m_next_branch_bp_sp) 417564d8bc2SJim Ingham return eStateRunning; 418564d8bc2SJim Ingham else 41930fdc8d8SChris Lattner return eStateStepping; 42030fdc8d8SChris Lattner } 42130fdc8d8SChris Lattner 422b9c1b51eSKate Stone bool ThreadPlanStepRange::MischiefManaged() { 423b9c1b51eSKate Stone // If we have pushed some plans between ShouldStop & MischiefManaged, then 424b9c1b51eSKate Stone // we're not done... 425b9c1b51eSKate Stone // I do this check first because we might have stepped somewhere that will 426b9c1b51eSKate Stone // fool InRange into 427b9c1b51eSKate Stone // thinking it needs to step past the end of that line. This happens, for 42805097246SAdrian Prantl // instance, when stepping over inlined code that is in the middle of the 42905097246SAdrian Prantl // current line. 430927bfa3fSJim Ingham 431927bfa3fSJim Ingham if (!m_no_more_plans) 432927bfa3fSJim Ingham return false; 433927bfa3fSJim Ingham 43430fdc8d8SChris Lattner bool done = true; 435b9c1b51eSKate Stone if (!IsPlanComplete()) { 436b9c1b51eSKate Stone if (InRange()) { 43730fdc8d8SChris Lattner done = false; 438b9c1b51eSKate Stone } else { 439b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 440e65b2cf2SEugene Zelenko done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true; 44130fdc8d8SChris Lattner } 442b5c0d1ccSJim Ingham } 44330fdc8d8SChris Lattner 444b9c1b51eSKate Stone if (done) { 4455160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 44630fdc8d8SChris Lattner if (log) 44730fdc8d8SChris Lattner log->Printf("Completed step through range plan."); 4480c61dee1SJim Ingham ClearNextBranchBreakpoint(); 44930fdc8d8SChris Lattner ThreadPlan::MischiefManaged(); 45030fdc8d8SChris Lattner return true; 451b9c1b51eSKate Stone } else { 45230fdc8d8SChris Lattner return false; 45330fdc8d8SChris Lattner } 45430fdc8d8SChris Lattner } 45564e7ead1SJim Ingham 456b9c1b51eSKate Stone bool ThreadPlanStepRange::IsPlanStale() { 4575160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 45864e7ead1SJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 45964e7ead1SJim Ingham 460b9c1b51eSKate Stone if (frame_order == eFrameCompareOlder) { 461b9c1b51eSKate Stone if (log) { 462b9c1b51eSKate Stone log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've " 463b9c1b51eSKate Stone "stepped out."); 46464e7ead1SJim Ingham } 46564e7ead1SJim Ingham return true; 466b9c1b51eSKate Stone } else if (frame_order == eFrameCompareEqual && InSymbol()) { 46705097246SAdrian Prantl // If we are not in a place we should step through, we've gotten stale. One 46805097246SAdrian Prantl // tricky bit here is that some stubs don't push a frame, so we should. 46964e7ead1SJim Ingham // check that we are in the same symbol. 470b9c1b51eSKate Stone if (!InRange()) { 47186aaa8a2SBoris Ulasevich // Set plan Complete when we reach next instruction just after the range 47286aaa8a2SBoris Ulasevich lldb::addr_t addr = m_thread.GetRegisterContext()->GetPC() - 1; 47386aaa8a2SBoris Ulasevich size_t num_ranges = m_address_ranges.size(); 47486aaa8a2SBoris Ulasevich for (size_t i = 0; i < num_ranges; i++) { 47586aaa8a2SBoris Ulasevich bool in_range = m_address_ranges[i].ContainsLoadAddress( 47686aaa8a2SBoris Ulasevich addr, m_thread.CalculateTarget().get()); 47786aaa8a2SBoris Ulasevich if (in_range) { 47886aaa8a2SBoris Ulasevich SetPlanComplete(); 47986aaa8a2SBoris Ulasevich } 48086aaa8a2SBoris Ulasevich } 48164e7ead1SJim Ingham return true; 48264e7ead1SJim Ingham } 48364e7ead1SJim Ingham } 48464e7ead1SJim Ingham return false; 48564e7ead1SJim Ingham } 486