180814287SRaphael Isemann //===-- ThreadPlanStepRange.cpp -------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 9e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanStepRange.h" 100c61dee1SJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h" 110c61dee1SJim Ingham #include "lldb/Breakpoint/BreakpointSite.h" 12564d8bc2SJim Ingham #include "lldb/Core/Disassembler.h" 1330fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 1430fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 15564d8bc2SJim Ingham #include "lldb/Target/ExecutionContext.h" 16f4b47e15SGreg Clayton #include "lldb/Target/Process.h" 17f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h" 18f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h" 19564d8bc2SJim Ingham #include "lldb/Target/Target.h" 20f4b47e15SGreg Clayton #include "lldb/Target/Thread.h" 21564d8bc2SJim Ingham #include "lldb/Target/ThreadPlanRunToAddress.h" 226f9e6901SZachary Turner #include "lldb/Utility/Log.h" 23bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 2430fdc8d8SChris Lattner 2530fdc8d8SChris Lattner using namespace lldb; 2630fdc8d8SChris Lattner using namespace lldb_private; 2730fdc8d8SChris Lattner 2805097246SAdrian Prantl // ThreadPlanStepRange: Step through a stack range, either stepping over or 2905097246SAdrian Prantl // into based on the value of \a type. 3030fdc8d8SChris Lattner 31b9c1b51eSKate Stone ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name, 32242e0ad7SJim Ingham Thread &thread, 33242e0ad7SJim Ingham const AddressRange &range, 34242e0ad7SJim Ingham const SymbolContext &addr_context, 352bdbfd50SJim Ingham lldb::RunMode stop_others, 36b9c1b51eSKate Stone bool given_ranges_only) 37b9c1b51eSKate Stone : ThreadPlan(kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 38b9c1b51eSKate Stone m_addr_context(addr_context), m_address_ranges(), 39b9c1b51eSKate Stone m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(), 40b9c1b51eSKate Stone m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false), 41b9c1b51eSKate Stone m_given_ranges_only(given_ranges_only) { 4217d023f6SJim Ingham m_use_fast_step = GetTarget().GetUseFastStepping(); 43c4c9fedcSJim Ingham AddRange(range); 44*e4598dc0SJim Ingham m_stack_id = thread.GetStackFrameAtIndex(0)->GetStackID(); 45*e4598dc0SJim Ingham StackFrameSP parent_stack = thread.GetStackFrameAtIndex(1); 4676447851SJim Ingham if (parent_stack) 4776447851SJim Ingham m_parent_stack_id = parent_stack->GetStackID(); 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner 50b9c1b51eSKate Stone ThreadPlanStepRange::~ThreadPlanStepRange() { ClearNextBranchBreakpoint(); } 51564d8bc2SJim Ingham 52b9c1b51eSKate Stone void ThreadPlanStepRange::DidPush() { 53564d8bc2SJim Ingham // See if we can find a "next range" breakpoint: 54564d8bc2SJim Ingham SetNextBranchBreakpoint(); 5530fdc8d8SChris Lattner } 5630fdc8d8SChris Lattner 57e103ae92SJonas Devlieghere bool ThreadPlanStepRange::ValidatePlan(Stream *error) { 58e103ae92SJonas Devlieghere if (m_could_not_resolve_hw_bp) { 59e103ae92SJonas Devlieghere if (error) 60e103ae92SJonas Devlieghere error->PutCString( 61e103ae92SJonas Devlieghere "Could not create hardware breakpoint for thread plan."); 62e103ae92SJonas Devlieghere return false; 63e103ae92SJonas Devlieghere } 64e103ae92SJonas Devlieghere return true; 65e103ae92SJonas Devlieghere } 6630fdc8d8SChris Lattner 67b9c1b51eSKate Stone Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) { 685160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 692cad65a5SGreg Clayton 702cad65a5SGreg Clayton const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 7163e5fb76SJonas Devlieghere LLDB_LOGF(log, "ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", 72b9c1b51eSKate Stone vote); 732cad65a5SGreg Clayton return vote; 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner 76b9c1b51eSKate Stone void ThreadPlanStepRange::AddRange(const AddressRange &new_range) { 7705097246SAdrian Prantl // For now I'm just adding the ranges. At some point we may want to condense 7805097246SAdrian Prantl // the ranges if they overlap, though I don't think it is likely to be very 7905097246SAdrian Prantl // important. 80c4c9fedcSJim Ingham m_address_ranges.push_back(new_range); 8156d40428SJim Ingham 82b9c1b51eSKate Stone // Fill the slot for this address range with an empty DisassemblerSP in the 8305097246SAdrian Prantl // instruction ranges. I want the indices to match, but I don't want to do 8405097246SAdrian Prantl // the work to disassemble this range if I don't step into it. 85564d8bc2SJim Ingham m_instruction_ranges.push_back(DisassemblerSP()); 86c4c9fedcSJim Ingham } 87c4c9fedcSJim Ingham 88b9c1b51eSKate Stone void ThreadPlanStepRange::DumpRanges(Stream *s) { 89*e4598dc0SJim Ingham Thread &thread = GetThread(); 90c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 91b9c1b51eSKate Stone if (num_ranges == 1) { 92*e4598dc0SJim Ingham m_address_ranges[0].Dump(s, &GetTarget(), Address::DumpStyleLoadAddress); 93b9c1b51eSKate Stone } else { 94b9c1b51eSKate Stone for (size_t i = 0; i < num_ranges; i++) { 958c0970feSPavel Labath s->Printf(" %" PRIu64 ": ", uint64_t(i)); 96*e4598dc0SJim Ingham m_address_ranges[i].Dump(s, &GetTarget(), Address::DumpStyleLoadAddress); 97c4c9fedcSJim Ingham } 98c4c9fedcSJim Ingham } 99c4c9fedcSJim Ingham } 100c4c9fedcSJim Ingham 101b9c1b51eSKate Stone bool ThreadPlanStepRange::InRange() { 1025160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 10330fdc8d8SChris Lattner bool ret_value = false; 104*e4598dc0SJim Ingham Thread &thread = GetThread(); 105*e4598dc0SJim Ingham lldb::addr_t pc_load_addr = thread.GetRegisterContext()->GetPC(); 10630fdc8d8SChris Lattner 107c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 108b9c1b51eSKate Stone for (size_t i = 0; i < num_ranges; i++) { 109*e4598dc0SJim Ingham ret_value = 110*e4598dc0SJim Ingham m_address_ranges[i].ContainsLoadAddress(pc_load_addr, &GetTarget()); 111c4c9fedcSJim Ingham if (ret_value) 112c4c9fedcSJim Ingham break; 113c4c9fedcSJim Ingham } 11430fdc8d8SChris Lattner 115b9c1b51eSKate Stone if (!ret_value && !m_given_ranges_only) { 11630fdc8d8SChris Lattner // See if we've just stepped to another part of the same line number... 117*e4598dc0SJim Ingham StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); 11830fdc8d8SChris Lattner 119b9c1b51eSKate Stone SymbolContext new_context( 120b9c1b51eSKate Stone frame->GetSymbolContext(eSymbolContextEverything)); 121b9c1b51eSKate Stone if (m_addr_context.line_entry.IsValid() && 122b9c1b51eSKate Stone new_context.line_entry.IsValid()) { 123b9c1b51eSKate Stone if (m_addr_context.line_entry.original_file == 124b9c1b51eSKate Stone new_context.line_entry.original_file) { 125b9c1b51eSKate Stone if (m_addr_context.line_entry.line == new_context.line_entry.line) { 12630fdc8d8SChris Lattner m_addr_context = new_context; 1278a777920SGreg Clayton const bool include_inlined_functions = 1288a777920SGreg Clayton GetKind() == eKindStepOverRange; 1298a777920SGreg Clayton AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange( 1308a777920SGreg Clayton include_inlined_functions)); 13130fdc8d8SChris Lattner ret_value = true; 132b9c1b51eSKate Stone if (log) { 13330fdc8d8SChris Lattner StreamString s; 134*e4598dc0SJim Ingham m_addr_context.line_entry.Dump(&s, &GetTarget(), true, 135*e4598dc0SJim Ingham Address::DumpStyleLoadAddress, 136b9c1b51eSKate Stone Address::DumpStyleLoadAddress, true); 13730fdc8d8SChris Lattner 13863e5fb76SJonas Devlieghere LLDB_LOGF( 13963e5fb76SJonas Devlieghere log, 140b9c1b51eSKate Stone "Step range plan stepped to another range of same line: %s", 141b9c1b51eSKate Stone s.GetData()); 14230fdc8d8SChris Lattner } 143b9c1b51eSKate Stone } else if (new_context.line_entry.line == 0) { 1442b89a531SJim Ingham new_context.line_entry.line = m_addr_context.line_entry.line; 1452b89a531SJim Ingham m_addr_context = new_context; 1468a777920SGreg Clayton const bool include_inlined_functions = 1478a777920SGreg Clayton GetKind() == eKindStepOverRange; 1488a777920SGreg Clayton AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange( 1498a777920SGreg Clayton include_inlined_functions)); 1502b89a531SJim Ingham ret_value = true; 151b9c1b51eSKate Stone if (log) { 1522b89a531SJim Ingham StreamString s; 153*e4598dc0SJim Ingham m_addr_context.line_entry.Dump(&s, &GetTarget(), true, 154*e4598dc0SJim Ingham Address::DumpStyleLoadAddress, 155b9c1b51eSKate Stone Address::DumpStyleLoadAddress, true); 1562b89a531SJim Ingham 15763e5fb76SJonas Devlieghere LLDB_LOGF(log, 15863e5fb76SJonas Devlieghere "Step range plan stepped to a range at linenumber 0 " 159b9c1b51eSKate Stone "stepping through that range: %s", 160b9c1b51eSKate Stone s.GetData()); 1612b89a531SJim Ingham } 162b9c1b51eSKate Stone } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress( 163*e4598dc0SJim Ingham &GetTarget()) != pc_load_addr) { 164b9c1b51eSKate Stone // Another thing that sometimes happens here is that we step out of 16505097246SAdrian Prantl // one line into the MIDDLE of another line. So far I mostly see 16605097246SAdrian Prantl // this due to bugs in the debug information. But we probably don't 16705097246SAdrian Prantl // want to be in the middle of a line range, so in that case reset 16805097246SAdrian Prantl // the stepping range to the line we've stepped into the middle of 16905097246SAdrian Prantl // and continue. 170843bfb2cSJim Ingham m_addr_context = new_context; 171c4c9fedcSJim Ingham m_address_ranges.clear(); 172c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 173843bfb2cSJim Ingham ret_value = true; 174b9c1b51eSKate Stone if (log) { 175843bfb2cSJim Ingham StreamString s; 176*e4598dc0SJim Ingham m_addr_context.line_entry.Dump(&s, &GetTarget(), true, 177*e4598dc0SJim Ingham Address::DumpStyleLoadAddress, 178b9c1b51eSKate Stone Address::DumpStyleLoadAddress, true); 179843bfb2cSJim Ingham 18063e5fb76SJonas Devlieghere LLDB_LOGF(log, 18163e5fb76SJonas Devlieghere "Step range plan stepped to the middle of new " 182b9c1b51eSKate Stone "line(%d): %s, continuing to clear this line.", 183b9c1b51eSKate Stone new_context.line_entry.line, s.GetData()); 184843bfb2cSJim Ingham } 185843bfb2cSJim Ingham } 186843bfb2cSJim Ingham } 18730fdc8d8SChris Lattner } 18830fdc8d8SChris Lattner } 18930fdc8d8SChris Lattner 19030fdc8d8SChris Lattner if (!ret_value && log) 19163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Step range plan out of range to 0x%" PRIx64, pc_load_addr); 19230fdc8d8SChris Lattner 19330fdc8d8SChris Lattner return ret_value; 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner 196b9c1b51eSKate Stone bool ThreadPlanStepRange::InSymbol() { 197*e4598dc0SJim Ingham lldb::addr_t cur_pc = GetThread().GetRegisterContext()->GetPC(); 198b9c1b51eSKate Stone if (m_addr_context.function != nullptr) { 199b9c1b51eSKate Stone return m_addr_context.function->GetAddressRange().ContainsLoadAddress( 200*e4598dc0SJim Ingham cur_pc, &GetTarget()); 201b9c1b51eSKate Stone } else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) { 202b9c1b51eSKate Stone AddressRange range(m_addr_context.symbol->GetAddressRef(), 203b9c1b51eSKate Stone m_addr_context.symbol->GetByteSize()); 204*e4598dc0SJim Ingham return range.ContainsLoadAddress(cur_pc, &GetTarget()); 20530fdc8d8SChris Lattner } 20630fdc8d8SChris Lattner return false; 20730fdc8d8SChris Lattner } 20830fdc8d8SChris Lattner 209b9c1b51eSKate Stone // FIXME: This should also handle inlining if we aren't going to do inlining in 210b9c1b51eSKate Stone // the 21130fdc8d8SChris Lattner // main stack. 21230fdc8d8SChris Lattner // 21330fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that 21430fdc8d8SChris Lattner // to the current list. 21530fdc8d8SChris Lattner 216b9c1b51eSKate Stone lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() { 217b5c0d1ccSJim Ingham FrameComparison frame_order; 218*e4598dc0SJim Ingham Thread &thread = GetThread(); 219*e4598dc0SJim Ingham StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID(); 2207ce490c6SJim Ingham 221b9c1b51eSKate Stone if (cur_frame_id == m_stack_id) { 222b5c0d1ccSJim Ingham frame_order = eFrameCompareEqual; 223b9c1b51eSKate Stone } else if (cur_frame_id < m_stack_id) { 224b5c0d1ccSJim Ingham frame_order = eFrameCompareYounger; 225b9c1b51eSKate Stone } else { 226*e4598dc0SJim Ingham StackFrameSP cur_parent_frame = thread.GetStackFrameAtIndex(1); 22776447851SJim Ingham StackID cur_parent_id; 22876447851SJim Ingham if (cur_parent_frame) 22976447851SJim Ingham cur_parent_id = cur_parent_frame->GetStackID(); 230b9c1b51eSKate Stone if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() && 231b9c1b51eSKate Stone m_parent_stack_id == cur_parent_id) 232862d1bbdSJim Ingham frame_order = eFrameCompareSameParent; 233862d1bbdSJim Ingham else 234b5c0d1ccSJim Ingham frame_order = eFrameCompareOlder; 23530fdc8d8SChris Lattner } 236b5c0d1ccSJim Ingham return frame_order; 23730fdc8d8SChris Lattner } 23830fdc8d8SChris Lattner 239b9c1b51eSKate Stone bool ThreadPlanStepRange::StopOthers() { 240434905b9SJim Ingham switch (m_stop_others) { 241434905b9SJim Ingham case lldb::eOnlyThisThread: 242434905b9SJim Ingham return true; 243434905b9SJim Ingham case lldb::eOnlyDuringStepping: 244434905b9SJim Ingham // If there is a call in the range of the next branch breakpoint, 245434905b9SJim Ingham // then we should always run all threads, since a call can execute 246434905b9SJim Ingham // arbitrary code which might for instance take a lock that's held 247434905b9SJim Ingham // by another thread. 248434905b9SJim Ingham return !m_found_calls; 249434905b9SJim Ingham case lldb::eAllThreads: 250434905b9SJim Ingham return false; 251434905b9SJim Ingham } 25205c3b36bSPavel Labath llvm_unreachable("Unhandled run mode!"); 25330fdc8d8SChris Lattner } 25430fdc8d8SChris Lattner 255b9c1b51eSKate Stone InstructionList *ThreadPlanStepRange::GetInstructionsForAddress( 256b9c1b51eSKate Stone lldb::addr_t addr, size_t &range_index, size_t &insn_offset) { 257564d8bc2SJim Ingham size_t num_ranges = m_address_ranges.size(); 258b9c1b51eSKate Stone for (size_t i = 0; i < num_ranges; i++) { 259b9c1b51eSKate Stone if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) { 260564d8bc2SJim Ingham // Some joker added a zero size range to the stepping range... 261564d8bc2SJim Ingham if (m_address_ranges[i].GetByteSize() == 0) 262e65b2cf2SEugene Zelenko return nullptr; 263564d8bc2SJim Ingham 264b9c1b51eSKate Stone if (!m_instruction_ranges[i]) { 265564d8bc2SJim Ingham // Disassemble the address range given: 266e65b2cf2SEugene Zelenko const char *plugin_name = nullptr; 267e65b2cf2SEugene Zelenko const char *flavor = nullptr; 2686b3e6d54SJason Molenda const bool prefer_file_cache = true; 269b9c1b51eSKate Stone m_instruction_ranges[i] = Disassembler::DisassembleRange( 27004592d5bSPavel Labath GetTarget().GetArchitecture(), plugin_name, flavor, GetTarget(), 271b9c1b51eSKate Stone m_address_ranges[i], prefer_file_cache); 272564d8bc2SJim Ingham } 273564d8bc2SJim Ingham if (!m_instruction_ranges[i]) 274e65b2cf2SEugene Zelenko return nullptr; 275b9c1b51eSKate Stone else { 276b9c1b51eSKate Stone // Find where we are in the instruction list as well. If we aren't at 27705097246SAdrian Prantl // an instruction, return nullptr. In this case, we're probably lost, 27805097246SAdrian Prantl // and shouldn't try to do anything fancy. 279564d8bc2SJim Ingham 280b9c1b51eSKate Stone insn_offset = 281b9c1b51eSKate Stone m_instruction_ranges[i] 282b9c1b51eSKate Stone ->GetInstructionList() 283b9c1b51eSKate Stone .GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 284564d8bc2SJim Ingham if (insn_offset == UINT32_MAX) 285e65b2cf2SEugene Zelenko return nullptr; 286b9c1b51eSKate Stone else { 287564d8bc2SJim Ingham range_index = i; 288564d8bc2SJim Ingham return &m_instruction_ranges[i]->GetInstructionList(); 289564d8bc2SJim Ingham } 290564d8bc2SJim Ingham } 291564d8bc2SJim Ingham } 292564d8bc2SJim Ingham } 293e65b2cf2SEugene Zelenko return nullptr; 294564d8bc2SJim Ingham } 295564d8bc2SJim Ingham 296b9c1b51eSKate Stone void ThreadPlanStepRange::ClearNextBranchBreakpoint() { 297b9c1b51eSKate Stone if (m_next_branch_bp_sp) { 2985160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 29963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Removing next branch breakpoint: %d.", 300b9c1b51eSKate Stone m_next_branch_bp_sp->GetID()); 301564d8bc2SJim Ingham GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID()); 302564d8bc2SJim Ingham m_next_branch_bp_sp.reset(); 303e103ae92SJonas Devlieghere m_could_not_resolve_hw_bp = false; 304434905b9SJim Ingham m_found_calls = false; 305564d8bc2SJim Ingham } 306564d8bc2SJim Ingham } 307564d8bc2SJim Ingham 308b9c1b51eSKate Stone bool ThreadPlanStepRange::SetNextBranchBreakpoint() { 3090c61dee1SJim Ingham if (m_next_branch_bp_sp) 3100c61dee1SJim Ingham return true; 3110c61dee1SJim Ingham 3125160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 313b9c1b51eSKate Stone // Stepping through ranges using breakpoints doesn't work yet, but with this 31405097246SAdrian Prantl // off we fall back to instruction single stepping. 3150c61dee1SJim Ingham if (!m_use_fast_step) 316564d8bc2SJim Ingham return false; 3170c61dee1SJim Ingham 318434905b9SJim Ingham // clear the m_found_calls, we'll rediscover it for this range. 319434905b9SJim Ingham m_found_calls = false; 320434905b9SJim Ingham 321564d8bc2SJim Ingham lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 322b9c1b51eSKate Stone // Find the current address in our address ranges, and fetch the disassembly 323b9c1b51eSKate Stone // if we haven't already: 324564d8bc2SJim Ingham size_t pc_index; 325564d8bc2SJim Ingham size_t range_index; 326b9c1b51eSKate Stone InstructionList *instructions = 327b9c1b51eSKate Stone GetInstructionsForAddress(cur_addr, range_index, pc_index); 328e65b2cf2SEugene Zelenko if (instructions == nullptr) 329564d8bc2SJim Ingham return false; 330b9c1b51eSKate Stone else { 331e76e7e93STed Woodward Target &target = GetThread().GetProcess()->GetTarget(); 332df225764SGreg Clayton const bool ignore_calls = GetKind() == eKindStepOverRange; 333df225764SGreg Clayton uint32_t branch_index = 334df225764SGreg Clayton instructions->GetIndexOfNextBranchInstruction(pc_index, target, 335434905b9SJim Ingham ignore_calls, 336434905b9SJim Ingham &m_found_calls); 337564d8bc2SJim Ingham 338564d8bc2SJim Ingham Address run_to_address; 339564d8bc2SJim Ingham 340564d8bc2SJim Ingham // If we didn't find a branch, run to the end of the range. 341b9c1b51eSKate Stone if (branch_index == UINT32_MAX) { 342a3f466b9SJim Ingham uint32_t last_index = instructions->GetSize() - 1; 343b9c1b51eSKate Stone if (last_index - pc_index > 1) { 344b9c1b51eSKate Stone InstructionSP last_inst = 345b9c1b51eSKate Stone instructions->GetInstructionAtIndex(last_index); 346a3f466b9SJim Ingham size_t last_inst_size = last_inst->GetOpcode().GetByteSize(); 347a3f466b9SJim Ingham run_to_address = last_inst->GetAddress(); 348a3f466b9SJim Ingham run_to_address.Slide(last_inst_size); 349a3f466b9SJim Ingham } 350b9c1b51eSKate Stone } else if (branch_index - pc_index > 1) { 351b9c1b51eSKate Stone run_to_address = 352b9c1b51eSKate Stone instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 353564d8bc2SJim Ingham } 3540c61dee1SJim Ingham 355b9c1b51eSKate Stone if (run_to_address.IsValid()) { 356564d8bc2SJim Ingham const bool is_internal = true; 357b9c1b51eSKate Stone m_next_branch_bp_sp = 358b9c1b51eSKate Stone GetTarget().CreateBreakpoint(run_to_address, is_internal, false); 359b9c1b51eSKate Stone if (m_next_branch_bp_sp) { 360e103ae92SJonas Devlieghere 361e103ae92SJonas Devlieghere if (m_next_branch_bp_sp->IsHardware() && 362e103ae92SJonas Devlieghere !m_next_branch_bp_sp->HasResolvedLocations()) 363e103ae92SJonas Devlieghere m_could_not_resolve_hw_bp = true; 364e103ae92SJonas Devlieghere 365b9c1b51eSKate Stone if (log) { 3660c61dee1SJim Ingham lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID; 367b9c1b51eSKate Stone BreakpointLocationSP bp_loc = 368b9c1b51eSKate Stone m_next_branch_bp_sp->GetLocationAtIndex(0); 369b9c1b51eSKate Stone if (bp_loc) { 3700c61dee1SJim Ingham BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite(); 371b9c1b51eSKate Stone if (bp_site) { 3720c61dee1SJim Ingham bp_site_id = bp_site->GetID(); 3730c61dee1SJim Ingham } 3740c61dee1SJim Ingham } 37563e5fb76SJonas Devlieghere LLDB_LOGF(log, 37663e5fb76SJonas Devlieghere "ThreadPlanStepRange::SetNextBranchBreakpoint - Setting " 377b9c1b51eSKate Stone "breakpoint %d (site %d) to run to address 0x%" PRIx64, 378b9c1b51eSKate Stone m_next_branch_bp_sp->GetID(), bp_site_id, 379*e4598dc0SJim Ingham run_to_address.GetLoadAddress(&m_process.GetTarget())); 3800c61dee1SJim Ingham } 381e103ae92SJonas Devlieghere 382*e4598dc0SJim Ingham m_next_branch_bp_sp->SetThreadID(m_tid); 3832995077dSJim Ingham m_next_branch_bp_sp->SetBreakpointKind("next-branch-location"); 384e103ae92SJonas Devlieghere 3850c61dee1SJim Ingham return true; 386b9c1b51eSKate Stone } else 3872995077dSJim Ingham return false; 388564d8bc2SJim Ingham } 389564d8bc2SJim Ingham } 390564d8bc2SJim Ingham return false; 391564d8bc2SJim Ingham } 392564d8bc2SJim Ingham 393b9c1b51eSKate Stone bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop( 394b9c1b51eSKate Stone lldb::StopInfoSP stop_info_sp) { 3955160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 396564d8bc2SJim Ingham if (!m_next_branch_bp_sp) 397564d8bc2SJim Ingham return false; 398564d8bc2SJim Ingham 399564d8bc2SJim Ingham break_id_t bp_site_id = stop_info_sp->GetValue(); 400b9c1b51eSKate Stone BreakpointSiteSP bp_site_sp = 401*e4598dc0SJim Ingham m_process.GetBreakpointSiteList().FindByID(bp_site_id); 4020c61dee1SJim Ingham if (!bp_site_sp) 4030c61dee1SJim Ingham return false; 4040c61dee1SJim Ingham else if (!bp_site_sp->IsBreakpointAtThisSite(m_next_branch_bp_sp->GetID())) 405564d8bc2SJim Ingham return false; 406b9c1b51eSKate Stone else { 4070c61dee1SJim Ingham // If we've hit the next branch breakpoint, then clear it. 4080c61dee1SJim Ingham size_t num_owners = bp_site_sp->GetNumberOfOwners(); 4090c61dee1SJim Ingham bool explains_stop = true; 410b9c1b51eSKate Stone // If all the owners are internal, then we are probably just stepping over 41105097246SAdrian Prantl // this range from multiple threads, or multiple frames, so we want to 41205097246SAdrian Prantl // continue. If one is not internal, then we should not explain the stop, 4130c61dee1SJim Ingham // and let the user breakpoint handle the stop. 414b9c1b51eSKate Stone for (size_t i = 0; i < num_owners; i++) { 415b9c1b51eSKate Stone if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) { 4160c61dee1SJim Ingham explains_stop = false; 4170c61dee1SJim Ingham break; 4180c61dee1SJim Ingham } 4190c61dee1SJim Ingham } 42063e5fb76SJonas Devlieghere LLDB_LOGF(log, 42163e5fb76SJonas Devlieghere "ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit " 422b9c1b51eSKate Stone "next range breakpoint which has %" PRIu64 423b9c1b51eSKate Stone " owners - explains stop: %u.", 424b9c1b51eSKate Stone (uint64_t)num_owners, explains_stop); 4250c61dee1SJim Ingham ClearNextBranchBreakpoint(); 4260c61dee1SJim Ingham return explains_stop; 4270c61dee1SJim Ingham } 428564d8bc2SJim Ingham } 429564d8bc2SJim Ingham 430b9c1b51eSKate Stone bool ThreadPlanStepRange::WillStop() { return true; } 43130fdc8d8SChris Lattner 432b9c1b51eSKate Stone StateType ThreadPlanStepRange::GetPlanRunState() { 433564d8bc2SJim Ingham if (m_next_branch_bp_sp) 434564d8bc2SJim Ingham return eStateRunning; 435564d8bc2SJim Ingham else 43630fdc8d8SChris Lattner return eStateStepping; 43730fdc8d8SChris Lattner } 43830fdc8d8SChris Lattner 439b9c1b51eSKate Stone bool ThreadPlanStepRange::MischiefManaged() { 440b9c1b51eSKate Stone // If we have pushed some plans between ShouldStop & MischiefManaged, then 441b9c1b51eSKate Stone // we're not done... 442b9c1b51eSKate Stone // I do this check first because we might have stepped somewhere that will 443b9c1b51eSKate Stone // fool InRange into 444b9c1b51eSKate Stone // thinking it needs to step past the end of that line. This happens, for 44505097246SAdrian Prantl // instance, when stepping over inlined code that is in the middle of the 44605097246SAdrian Prantl // current line. 447927bfa3fSJim Ingham 448927bfa3fSJim Ingham if (!m_no_more_plans) 449927bfa3fSJim Ingham return false; 450927bfa3fSJim Ingham 45130fdc8d8SChris Lattner bool done = true; 452b9c1b51eSKate Stone if (!IsPlanComplete()) { 453b9c1b51eSKate Stone if (InRange()) { 45430fdc8d8SChris Lattner done = false; 455b9c1b51eSKate Stone } else { 456b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 457e65b2cf2SEugene Zelenko done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true; 45830fdc8d8SChris Lattner } 459b5c0d1ccSJim Ingham } 46030fdc8d8SChris Lattner 461b9c1b51eSKate Stone if (done) { 4625160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 46363e5fb76SJonas Devlieghere LLDB_LOGF(log, "Completed step through range plan."); 4640c61dee1SJim Ingham ClearNextBranchBreakpoint(); 46530fdc8d8SChris Lattner ThreadPlan::MischiefManaged(); 46630fdc8d8SChris Lattner return true; 467b9c1b51eSKate Stone } else { 46830fdc8d8SChris Lattner return false; 46930fdc8d8SChris Lattner } 47030fdc8d8SChris Lattner } 47164e7ead1SJim Ingham 472b9c1b51eSKate Stone bool ThreadPlanStepRange::IsPlanStale() { 4735160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 47464e7ead1SJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 47564e7ead1SJim Ingham 476b9c1b51eSKate Stone if (frame_order == eFrameCompareOlder) { 477b9c1b51eSKate Stone if (log) { 47863e5fb76SJonas Devlieghere LLDB_LOGF(log, "ThreadPlanStepRange::IsPlanStale returning true, we've " 479b9c1b51eSKate Stone "stepped out."); 48064e7ead1SJim Ingham } 48164e7ead1SJim Ingham return true; 482b9c1b51eSKate Stone } else if (frame_order == eFrameCompareEqual && InSymbol()) { 48305097246SAdrian Prantl // If we are not in a place we should step through, we've gotten stale. One 48405097246SAdrian Prantl // tricky bit here is that some stubs don't push a frame, so we should. 48564e7ead1SJim Ingham // check that we are in the same symbol. 486b9c1b51eSKate Stone if (!InRange()) { 48786aaa8a2SBoris Ulasevich // Set plan Complete when we reach next instruction just after the range 488*e4598dc0SJim Ingham lldb::addr_t addr = GetThread().GetRegisterContext()->GetPC() - 1; 48986aaa8a2SBoris Ulasevich size_t num_ranges = m_address_ranges.size(); 49086aaa8a2SBoris Ulasevich for (size_t i = 0; i < num_ranges; i++) { 491*e4598dc0SJim Ingham bool in_range = 492*e4598dc0SJim Ingham m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget()); 49386aaa8a2SBoris Ulasevich if (in_range) { 49486aaa8a2SBoris Ulasevich SetPlanComplete(); 49586aaa8a2SBoris Ulasevich } 49686aaa8a2SBoris Ulasevich } 49764e7ead1SJim Ingham return true; 49864e7ead1SJim Ingham } 49964e7ead1SJim Ingham } 50064e7ead1SJim Ingham return false; 50164e7ead1SJim Ingham } 502