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 1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepRange.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner 1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 18564d8bc2SJim Ingham #include "lldb/Core/Disassembler.h" 1930fdc8d8SChris Lattner #include "lldb/Core/Log.h" 2030fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 2130fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 2230fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 23564d8bc2SJim Ingham #include "lldb/Target/ExecutionContext.h" 24f4b47e15SGreg Clayton #include "lldb/Target/Process.h" 25f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h" 26f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h" 27564d8bc2SJim Ingham #include "lldb/Target/Target.h" 28f4b47e15SGreg Clayton #include "lldb/Target/Thread.h" 29564d8bc2SJim Ingham #include "lldb/Target/ThreadPlanRunToAddress.h" 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner using namespace lldb; 3230fdc8d8SChris Lattner using namespace lldb_private; 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner 3530fdc8d8SChris Lattner //---------------------------------------------------------------------- 3630fdc8d8SChris Lattner // ThreadPlanStepRange: Step through a stack range, either stepping over or into 3730fdc8d8SChris Lattner // based on the value of \a type. 3830fdc8d8SChris Lattner //---------------------------------------------------------------------- 3930fdc8d8SChris Lattner 40242e0ad7SJim Ingham ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, 41242e0ad7SJim Ingham const char *name, 42242e0ad7SJim Ingham Thread &thread, 43242e0ad7SJim Ingham const AddressRange &range, 44242e0ad7SJim Ingham const SymbolContext &addr_context, 45242e0ad7SJim Ingham lldb::RunMode stop_others) : 4635b21fefSJim Ingham ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 4730fdc8d8SChris Lattner m_addr_context (addr_context), 48c4c9fedcSJim Ingham m_address_ranges (), 4930fdc8d8SChris Lattner m_stop_others (stop_others), 5030fdc8d8SChris Lattner m_stack_id (), 51c982c768SGreg Clayton m_no_more_plans (false), 5230fdc8d8SChris Lattner m_first_run_event (true) 5330fdc8d8SChris Lattner { 54c4c9fedcSJim Ingham AddRange(range); 5530fdc8d8SChris Lattner m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner ThreadPlanStepRange::~ThreadPlanStepRange () 5930fdc8d8SChris Lattner { 60564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 61564d8bc2SJim Ingham } 62564d8bc2SJim Ingham 63564d8bc2SJim Ingham void 64564d8bc2SJim Ingham ThreadPlanStepRange::DidPush () 65564d8bc2SJim Ingham { 66564d8bc2SJim Ingham // See if we can find a "next range" breakpoint: 67564d8bc2SJim Ingham SetNextBranchBreakpoint(); 6830fdc8d8SChris Lattner } 6930fdc8d8SChris Lattner 7030fdc8d8SChris Lattner bool 7130fdc8d8SChris Lattner ThreadPlanStepRange::ValidatePlan (Stream *error) 7230fdc8d8SChris Lattner { 7330fdc8d8SChris Lattner return true; 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner 7630fdc8d8SChris Lattner Vote 7730fdc8d8SChris Lattner ThreadPlanStepRange::ShouldReportStop (Event *event_ptr) 7830fdc8d8SChris Lattner { 792d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 802cad65a5SGreg Clayton 812cad65a5SGreg Clayton const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 822cad65a5SGreg Clayton if (log) 83411c0ce8SGreg Clayton log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote); 842cad65a5SGreg Clayton return vote; 8530fdc8d8SChris Lattner } 8630fdc8d8SChris Lattner 87c4c9fedcSJim Ingham void 88c4c9fedcSJim Ingham ThreadPlanStepRange::AddRange(const AddressRange &new_range) 89c4c9fedcSJim Ingham { 90c4c9fedcSJim Ingham // For now I'm just adding the ranges. At some point we may want to 91c4c9fedcSJim Ingham // condense the ranges if they overlap, though I don't think it is likely 92c4c9fedcSJim Ingham // to be very important. 93c4c9fedcSJim Ingham m_address_ranges.push_back (new_range); 94564d8bc2SJim Ingham m_instruction_ranges.push_back (DisassemblerSP()); 95c4c9fedcSJim Ingham } 96c4c9fedcSJim Ingham 97c4c9fedcSJim Ingham void 98c4c9fedcSJim Ingham ThreadPlanStepRange::DumpRanges(Stream *s) 99c4c9fedcSJim Ingham { 100c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 101c4c9fedcSJim Ingham if (num_ranges == 1) 102c4c9fedcSJim Ingham { 1031ac04c30SGreg Clayton m_address_ranges[0].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress); 104c4c9fedcSJim Ingham } 105c4c9fedcSJim Ingham else 106c4c9fedcSJim Ingham { 107c4c9fedcSJim Ingham for (size_t i = 0; i < num_ranges; i++) 108c4c9fedcSJim Ingham { 109c4c9fedcSJim Ingham s->PutCString("%d: "); 1101ac04c30SGreg Clayton m_address_ranges[i].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress); 111c4c9fedcSJim Ingham } 112c4c9fedcSJim Ingham } 113c4c9fedcSJim Ingham } 114c4c9fedcSJim Ingham 11530fdc8d8SChris Lattner bool 11630fdc8d8SChris Lattner ThreadPlanStepRange::InRange () 11730fdc8d8SChris Lattner { 1182d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 11930fdc8d8SChris Lattner bool ret_value = false; 12030fdc8d8SChris Lattner 12130fdc8d8SChris Lattner lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 12230fdc8d8SChris Lattner 123c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 124c4c9fedcSJim Ingham for (size_t i = 0; i < num_ranges; i++) 125c4c9fedcSJim Ingham { 1261ac04c30SGreg Clayton ret_value = m_address_ranges[i].ContainsLoadAddress(pc_load_addr, m_thread.CalculateTarget().get()); 127c4c9fedcSJim Ingham if (ret_value) 128c4c9fedcSJim Ingham break; 129c4c9fedcSJim Ingham } 13030fdc8d8SChris Lattner 13130fdc8d8SChris Lattner if (!ret_value) 13230fdc8d8SChris Lattner { 13330fdc8d8SChris Lattner // See if we've just stepped to another part of the same line number... 13430fdc8d8SChris Lattner StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 13530fdc8d8SChris Lattner 13630fdc8d8SChris Lattner SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 13730fdc8d8SChris Lattner if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 13830fdc8d8SChris Lattner { 139843bfb2cSJim Ingham if (m_addr_context.line_entry.file == new_context.line_entry.file) 140843bfb2cSJim Ingham { 141843bfb2cSJim Ingham if (m_addr_context.line_entry.line == new_context.line_entry.line) 14230fdc8d8SChris Lattner { 14330fdc8d8SChris Lattner m_addr_context = new_context; 144c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 14530fdc8d8SChris Lattner ret_value = true; 14630fdc8d8SChris Lattner if (log) 14730fdc8d8SChris Lattner { 14830fdc8d8SChris Lattner StreamString s; 149927bfa3fSJim Ingham m_addr_context.line_entry.Dump (&s, 1501ac04c30SGreg Clayton m_thread.CalculateTarget().get(), 151927bfa3fSJim Ingham true, 152927bfa3fSJim Ingham Address::DumpStyleLoadAddress, 153927bfa3fSJim Ingham Address::DumpStyleLoadAddress, 154927bfa3fSJim Ingham true); 15530fdc8d8SChris Lattner 15630fdc8d8SChris Lattner log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 15730fdc8d8SChris Lattner } 15830fdc8d8SChris Lattner } 1591ac04c30SGreg Clayton else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get()) 160843bfb2cSJim Ingham != pc_load_addr) 161843bfb2cSJim Ingham { 162843bfb2cSJim Ingham // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another 163843bfb2cSJim Ingham // line. So far I mostly see this due to bugs in the debug information. 164843bfb2cSJim Ingham // But we probably don't want to be in the middle of a line range, so in that case reset the stepping 165843bfb2cSJim Ingham // range to the line we've stepped into the middle of and continue. 166843bfb2cSJim Ingham m_addr_context = new_context; 167c4c9fedcSJim Ingham m_address_ranges.clear(); 168c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 169843bfb2cSJim Ingham ret_value = true; 170843bfb2cSJim Ingham if (log) 171843bfb2cSJim Ingham { 172843bfb2cSJim Ingham StreamString s; 173927bfa3fSJim Ingham m_addr_context.line_entry.Dump (&s, 1741ac04c30SGreg Clayton m_thread.CalculateTarget().get(), 175927bfa3fSJim Ingham true, 176927bfa3fSJim Ingham Address::DumpStyleLoadAddress, 177927bfa3fSJim Ingham Address::DumpStyleLoadAddress, 178927bfa3fSJim Ingham true); 179843bfb2cSJim Ingham 180843bfb2cSJim Ingham log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.", 181843bfb2cSJim Ingham new_context.line_entry.line, 182843bfb2cSJim Ingham s.GetData()); 183843bfb2cSJim Ingham } 184843bfb2cSJim Ingham 185843bfb2cSJim Ingham } 186843bfb2cSJim Ingham } 187843bfb2cSJim Ingham 18830fdc8d8SChris Lattner } 18930fdc8d8SChris Lattner 19030fdc8d8SChris Lattner } 19130fdc8d8SChris Lattner 19230fdc8d8SChris Lattner if (!ret_value && log) 193*d01b2953SDaniel Malea log->Printf ("Step range plan out of range to 0x%" PRIx64, pc_load_addr); 19430fdc8d8SChris Lattner 19530fdc8d8SChris Lattner return ret_value; 19630fdc8d8SChris Lattner } 19730fdc8d8SChris Lattner 19830fdc8d8SChris Lattner bool 19930fdc8d8SChris Lattner ThreadPlanStepRange::InSymbol() 20030fdc8d8SChris Lattner { 20130fdc8d8SChris Lattner lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 20230fdc8d8SChris Lattner if (m_addr_context.function != NULL) 20330fdc8d8SChris Lattner { 2041ac04c30SGreg Clayton return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 20530fdc8d8SChris Lattner } 206e7612134SGreg Clayton else if (m_addr_context.symbol) 20730fdc8d8SChris Lattner { 208e7612134SGreg Clayton AddressRange range(m_addr_context.symbol->GetAddress(), m_addr_context.symbol->GetByteSize()); 209e7612134SGreg Clayton return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 21030fdc8d8SChris Lattner } 21130fdc8d8SChris Lattner return false; 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner 21430fdc8d8SChris Lattner // FIXME: This should also handle inlining if we aren't going to do inlining in the 21530fdc8d8SChris Lattner // main stack. 21630fdc8d8SChris Lattner // 21730fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that 21830fdc8d8SChris Lattner // to the current list. 21930fdc8d8SChris Lattner 220b5c0d1ccSJim Ingham lldb::FrameComparison 221b5c0d1ccSJim Ingham ThreadPlanStepRange::CompareCurrentFrameToStartFrame() 22230fdc8d8SChris Lattner { 223b5c0d1ccSJim Ingham FrameComparison frame_order; 2247ce490c6SJim Ingham 225b5c0d1ccSJim Ingham StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 2267ce490c6SJim Ingham 227b5c0d1ccSJim Ingham if (cur_frame_id == m_stack_id) 22830fdc8d8SChris Lattner { 229b5c0d1ccSJim Ingham frame_order = eFrameCompareEqual; 23030fdc8d8SChris Lattner } 231b5c0d1ccSJim Ingham else if (cur_frame_id < m_stack_id) 23230fdc8d8SChris Lattner { 233b5c0d1ccSJim Ingham frame_order = eFrameCompareYounger; 23430fdc8d8SChris Lattner } 23530fdc8d8SChris Lattner else 23630fdc8d8SChris Lattner { 237b5c0d1ccSJim Ingham frame_order = eFrameCompareOlder; 23830fdc8d8SChris Lattner } 239b5c0d1ccSJim Ingham return frame_order; 24030fdc8d8SChris Lattner } 24130fdc8d8SChris Lattner 24230fdc8d8SChris Lattner bool 24330fdc8d8SChris Lattner ThreadPlanStepRange::StopOthers () 24430fdc8d8SChris Lattner { 24530fdc8d8SChris Lattner if (m_stop_others == lldb::eOnlyThisThread 24630fdc8d8SChris Lattner || m_stop_others == lldb::eOnlyDuringStepping) 24730fdc8d8SChris Lattner return true; 24830fdc8d8SChris Lattner else 24930fdc8d8SChris Lattner return false; 25030fdc8d8SChris Lattner } 25130fdc8d8SChris Lattner 252564d8bc2SJim Ingham InstructionList * 253564d8bc2SJim Ingham ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset) 254564d8bc2SJim Ingham { 255564d8bc2SJim Ingham size_t num_ranges = m_address_ranges.size(); 256564d8bc2SJim Ingham for (size_t i = 0; i < num_ranges; i++) 257564d8bc2SJim Ingham { 258564d8bc2SJim Ingham if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) 259564d8bc2SJim Ingham { 260564d8bc2SJim Ingham // Some joker added a zero size range to the stepping range... 261564d8bc2SJim Ingham if (m_address_ranges[i].GetByteSize() == 0) 262564d8bc2SJim Ingham return NULL; 263564d8bc2SJim Ingham 264564d8bc2SJim Ingham if (!m_instruction_ranges[i]) 265564d8bc2SJim Ingham { 266564d8bc2SJim Ingham //Disassemble the address range given: 267564d8bc2SJim Ingham ExecutionContext exe_ctx (m_thread.GetProcess()); 268564d8bc2SJim Ingham m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), 269564d8bc2SJim Ingham NULL, 270564d8bc2SJim Ingham exe_ctx, 271564d8bc2SJim Ingham m_address_ranges[i]); 272564d8bc2SJim Ingham 273564d8bc2SJim Ingham } 274564d8bc2SJim Ingham if (!m_instruction_ranges[i]) 275564d8bc2SJim Ingham return NULL; 276564d8bc2SJim Ingham else 277564d8bc2SJim Ingham { 278564d8bc2SJim Ingham // Find where we are in the instruction list as well. If we aren't at an instruction, 279564d8bc2SJim Ingham // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy. 280564d8bc2SJim Ingham 281564d8bc2SJim Ingham insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 282564d8bc2SJim Ingham if (insn_offset == UINT32_MAX) 283564d8bc2SJim Ingham return NULL; 284564d8bc2SJim Ingham else 285564d8bc2SJim Ingham { 286564d8bc2SJim Ingham range_index = i; 287564d8bc2SJim Ingham return &m_instruction_ranges[i]->GetInstructionList(); 288564d8bc2SJim Ingham } 289564d8bc2SJim Ingham } 290564d8bc2SJim Ingham } 291564d8bc2SJim Ingham } 292564d8bc2SJim Ingham return NULL; 293564d8bc2SJim Ingham } 294564d8bc2SJim Ingham 295564d8bc2SJim Ingham void 296564d8bc2SJim Ingham ThreadPlanStepRange::ClearNextBranchBreakpoint() 297564d8bc2SJim Ingham { 298564d8bc2SJim Ingham if (m_next_branch_bp_sp) 299564d8bc2SJim Ingham { 300564d8bc2SJim Ingham GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); 301564d8bc2SJim Ingham m_next_branch_bp_sp.reset(); 302564d8bc2SJim Ingham } 303564d8bc2SJim Ingham } 304564d8bc2SJim Ingham 305564d8bc2SJim Ingham bool 306564d8bc2SJim Ingham ThreadPlanStepRange::SetNextBranchBreakpoint () 307564d8bc2SJim Ingham { 308564d8bc2SJim Ingham // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction 309564d8bc2SJim Ingham // single stepping. 310564d8bc2SJim Ingham return false; 311564d8bc2SJim Ingham // Always clear the next branch breakpoint, we don't want to leave one of these stranded. 312564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 313564d8bc2SJim Ingham lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 314564d8bc2SJim Ingham // Find the current address in our address ranges, and fetch the disassembly if we haven't already: 315564d8bc2SJim Ingham size_t pc_index; 316564d8bc2SJim Ingham size_t range_index; 317564d8bc2SJim Ingham InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); 318564d8bc2SJim Ingham if (instructions == NULL) 319564d8bc2SJim Ingham return false; 320564d8bc2SJim Ingham else 321564d8bc2SJim Ingham { 322564d8bc2SJim Ingham uint32_t branch_index; 323564d8bc2SJim Ingham branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index); 324564d8bc2SJim Ingham 325564d8bc2SJim Ingham Address run_to_address; 326564d8bc2SJim Ingham 327564d8bc2SJim Ingham // If we didn't find a branch, run to the end of the range. 328564d8bc2SJim Ingham if (branch_index == UINT32_MAX) 329564d8bc2SJim Ingham { 330564d8bc2SJim Ingham branch_index = instructions->GetSize() - 2; 331564d8bc2SJim Ingham } 332564d8bc2SJim Ingham if (branch_index - pc_index > 1) 333564d8bc2SJim Ingham { 334564d8bc2SJim Ingham const bool is_internal = true; 335564d8bc2SJim Ingham run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 336564d8bc2SJim Ingham m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); 337564d8bc2SJim Ingham m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 338564d8bc2SJim Ingham return true; 339564d8bc2SJim Ingham } 340564d8bc2SJim Ingham } 341564d8bc2SJim Ingham return false; 342564d8bc2SJim Ingham } 343564d8bc2SJim Ingham 344564d8bc2SJim Ingham bool 345564d8bc2SJim Ingham ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) 346564d8bc2SJim Ingham { 347564d8bc2SJim Ingham if (!m_next_branch_bp_sp) 348564d8bc2SJim Ingham return false; 349564d8bc2SJim Ingham 350564d8bc2SJim Ingham break_id_t bp_site_id = stop_info_sp->GetValue(); 351564d8bc2SJim Ingham BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 352564d8bc2SJim Ingham if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) 353564d8bc2SJim Ingham return false; 354564d8bc2SJim Ingham else 355564d8bc2SJim Ingham return bp_site_sp->GetNumberOfOwners() == 1; 356564d8bc2SJim Ingham } 357564d8bc2SJim Ingham 358564d8bc2SJim Ingham bool 35930fdc8d8SChris Lattner ThreadPlanStepRange::WillStop () 36030fdc8d8SChris Lattner { 36130fdc8d8SChris Lattner return true; 36230fdc8d8SChris Lattner } 36330fdc8d8SChris Lattner 36430fdc8d8SChris Lattner StateType 36506e827ccSJim Ingham ThreadPlanStepRange::GetPlanRunState () 36630fdc8d8SChris Lattner { 367564d8bc2SJim Ingham if (m_next_branch_bp_sp) 368564d8bc2SJim Ingham return eStateRunning; 369564d8bc2SJim Ingham else 37030fdc8d8SChris Lattner return eStateStepping; 37130fdc8d8SChris Lattner } 37230fdc8d8SChris Lattner 37330fdc8d8SChris Lattner bool 37430fdc8d8SChris Lattner ThreadPlanStepRange::MischiefManaged () 37530fdc8d8SChris Lattner { 376927bfa3fSJim Ingham // If we have pushed some plans between ShouldStop & MischiefManaged, then we're not done... 377927bfa3fSJim Ingham // I do this check first because we might have stepped somewhere that will fool InRange into 378927bfa3fSJim Ingham // thinking it needs to step past the end of that line. This happens, for instance, when stepping 379927bfa3fSJim Ingham // over inlined code that is in the middle of the current line. 380927bfa3fSJim Ingham 381927bfa3fSJim Ingham if (!m_no_more_plans) 382927bfa3fSJim Ingham return false; 383927bfa3fSJim Ingham 38430fdc8d8SChris Lattner bool done = true; 38530fdc8d8SChris Lattner if (!IsPlanComplete()) 38630fdc8d8SChris Lattner { 38730fdc8d8SChris Lattner if (InRange()) 38830fdc8d8SChris Lattner { 38930fdc8d8SChris Lattner done = false; 39030fdc8d8SChris Lattner } 391b5c0d1ccSJim Ingham else 392b5c0d1ccSJim Ingham { 393b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 394b5c0d1ccSJim Ingham if (frame_order != eFrameCompareOlder) 39530fdc8d8SChris Lattner { 39630fdc8d8SChris Lattner if (m_no_more_plans) 39730fdc8d8SChris Lattner done = true; 39830fdc8d8SChris Lattner else 39930fdc8d8SChris Lattner done = false; 40030fdc8d8SChris Lattner } 40130fdc8d8SChris Lattner else 40230fdc8d8SChris Lattner done = true; 40330fdc8d8SChris Lattner } 404b5c0d1ccSJim Ingham } 40530fdc8d8SChris Lattner 40630fdc8d8SChris Lattner if (done) 40730fdc8d8SChris Lattner { 4082d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 40930fdc8d8SChris Lattner if (log) 41030fdc8d8SChris Lattner log->Printf("Completed step through range plan."); 41130fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 41230fdc8d8SChris Lattner return true; 41330fdc8d8SChris Lattner } 41430fdc8d8SChris Lattner else 41530fdc8d8SChris Lattner { 41630fdc8d8SChris Lattner return false; 41730fdc8d8SChris Lattner } 41830fdc8d8SChris Lattner 41930fdc8d8SChris Lattner } 42064e7ead1SJim Ingham 42164e7ead1SJim Ingham bool 42264e7ead1SJim Ingham ThreadPlanStepRange::IsPlanStale () 42364e7ead1SJim Ingham { 42464e7ead1SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 42564e7ead1SJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 42664e7ead1SJim Ingham 42764e7ead1SJim Ingham if (frame_order == eFrameCompareOlder) 42864e7ead1SJim Ingham { 42964e7ead1SJim Ingham if (log) 43064e7ead1SJim Ingham { 43164e7ead1SJim Ingham log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out."); 43264e7ead1SJim Ingham } 43364e7ead1SJim Ingham return true; 43464e7ead1SJim Ingham } 43564e7ead1SJim Ingham else if (frame_order == eFrameCompareEqual && InSymbol()) 43664e7ead1SJim Ingham { 43764e7ead1SJim Ingham // If we are not in a place we should step through, we've gotten stale. 43864e7ead1SJim Ingham // One tricky bit here is that some stubs don't push a frame, so we should. 43964e7ead1SJim Ingham // check that we are in the same symbol. 44064e7ead1SJim Ingham if (!InRange()) 44164e7ead1SJim Ingham { 44264e7ead1SJim Ingham return true; 44364e7ead1SJim Ingham } 44464e7ead1SJim Ingham } 44564e7ead1SJim Ingham return false; 44664e7ead1SJim Ingham } 447