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; 149c4c9fedcSJim Ingham m_addr_context.line_entry.range.Dump (&s, 1501ac04c30SGreg Clayton m_thread.CalculateTarget().get(), 151c4c9fedcSJim Ingham Address::DumpStyleLoadAddress); 15230fdc8d8SChris Lattner 15330fdc8d8SChris Lattner log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 15430fdc8d8SChris Lattner } 15530fdc8d8SChris Lattner } 1561ac04c30SGreg Clayton else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get()) 157843bfb2cSJim Ingham != pc_load_addr) 158843bfb2cSJim Ingham { 159843bfb2cSJim Ingham // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another 160843bfb2cSJim Ingham // line. So far I mostly see this due to bugs in the debug information. 161843bfb2cSJim Ingham // But we probably don't want to be in the middle of a line range, so in that case reset the stepping 162843bfb2cSJim Ingham // range to the line we've stepped into the middle of and continue. 163843bfb2cSJim Ingham m_addr_context = new_context; 164c4c9fedcSJim Ingham m_address_ranges.clear(); 165c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 166843bfb2cSJim Ingham ret_value = true; 167843bfb2cSJim Ingham if (log) 168843bfb2cSJim Ingham { 169843bfb2cSJim Ingham StreamString s; 170c4c9fedcSJim Ingham m_addr_context.line_entry.range.Dump (&s, 1711ac04c30SGreg Clayton m_thread.CalculateTarget().get(), 172c4c9fedcSJim Ingham Address::DumpStyleLoadAddress); 173843bfb2cSJim Ingham 174843bfb2cSJim Ingham log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.", 175843bfb2cSJim Ingham new_context.line_entry.line, 176843bfb2cSJim Ingham s.GetData()); 177843bfb2cSJim Ingham } 178843bfb2cSJim Ingham 179843bfb2cSJim Ingham } 180843bfb2cSJim Ingham } 181843bfb2cSJim Ingham 18230fdc8d8SChris Lattner } 18330fdc8d8SChris Lattner 18430fdc8d8SChris Lattner } 18530fdc8d8SChris Lattner 18630fdc8d8SChris Lattner if (!ret_value && log) 18730fdc8d8SChris Lattner log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr); 18830fdc8d8SChris Lattner 18930fdc8d8SChris Lattner return ret_value; 19030fdc8d8SChris Lattner } 19130fdc8d8SChris Lattner 19230fdc8d8SChris Lattner bool 19330fdc8d8SChris Lattner ThreadPlanStepRange::InSymbol() 19430fdc8d8SChris Lattner { 19530fdc8d8SChris Lattner lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 19630fdc8d8SChris Lattner if (m_addr_context.function != NULL) 19730fdc8d8SChris Lattner { 1981ac04c30SGreg Clayton return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 19930fdc8d8SChris Lattner } 200e7612134SGreg Clayton else if (m_addr_context.symbol) 20130fdc8d8SChris Lattner { 202e7612134SGreg Clayton AddressRange range(m_addr_context.symbol->GetAddress(), m_addr_context.symbol->GetByteSize()); 203e7612134SGreg Clayton return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get()); 20430fdc8d8SChris Lattner } 20530fdc8d8SChris Lattner return false; 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner 20830fdc8d8SChris Lattner // FIXME: This should also handle inlining if we aren't going to do inlining in 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 214b5c0d1ccSJim Ingham lldb::FrameComparison 215b5c0d1ccSJim Ingham ThreadPlanStepRange::CompareCurrentFrameToStartFrame() 21630fdc8d8SChris Lattner { 217b5c0d1ccSJim Ingham FrameComparison frame_order; 2187ce490c6SJim Ingham 219b5c0d1ccSJim Ingham StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 2207ce490c6SJim Ingham 221b5c0d1ccSJim Ingham if (cur_frame_id == m_stack_id) 22230fdc8d8SChris Lattner { 223b5c0d1ccSJim Ingham frame_order = eFrameCompareEqual; 22430fdc8d8SChris Lattner } 225b5c0d1ccSJim Ingham else if (cur_frame_id < m_stack_id) 22630fdc8d8SChris Lattner { 227b5c0d1ccSJim Ingham frame_order = eFrameCompareYounger; 22830fdc8d8SChris Lattner } 22930fdc8d8SChris Lattner else 23030fdc8d8SChris Lattner { 231b5c0d1ccSJim Ingham frame_order = eFrameCompareOlder; 23230fdc8d8SChris Lattner } 233b5c0d1ccSJim Ingham return frame_order; 23430fdc8d8SChris Lattner } 23530fdc8d8SChris Lattner 23630fdc8d8SChris Lattner bool 23730fdc8d8SChris Lattner ThreadPlanStepRange::StopOthers () 23830fdc8d8SChris Lattner { 23930fdc8d8SChris Lattner if (m_stop_others == lldb::eOnlyThisThread 24030fdc8d8SChris Lattner || m_stop_others == lldb::eOnlyDuringStepping) 24130fdc8d8SChris Lattner return true; 24230fdc8d8SChris Lattner else 24330fdc8d8SChris Lattner return false; 24430fdc8d8SChris Lattner } 24530fdc8d8SChris Lattner 246564d8bc2SJim Ingham InstructionList * 247564d8bc2SJim Ingham ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset) 248564d8bc2SJim Ingham { 249564d8bc2SJim Ingham size_t num_ranges = m_address_ranges.size(); 250564d8bc2SJim Ingham for (size_t i = 0; i < num_ranges; i++) 251564d8bc2SJim Ingham { 252564d8bc2SJim Ingham if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) 253564d8bc2SJim Ingham { 254564d8bc2SJim Ingham // Some joker added a zero size range to the stepping range... 255564d8bc2SJim Ingham if (m_address_ranges[i].GetByteSize() == 0) 256564d8bc2SJim Ingham return NULL; 257564d8bc2SJim Ingham 258564d8bc2SJim Ingham if (!m_instruction_ranges[i]) 259564d8bc2SJim Ingham { 260564d8bc2SJim Ingham //Disassemble the address range given: 261564d8bc2SJim Ingham ExecutionContext exe_ctx (m_thread.GetProcess()); 262564d8bc2SJim Ingham m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), 263564d8bc2SJim Ingham NULL, 264564d8bc2SJim Ingham exe_ctx, 265564d8bc2SJim Ingham m_address_ranges[i]); 266564d8bc2SJim Ingham 267564d8bc2SJim Ingham } 268564d8bc2SJim Ingham if (!m_instruction_ranges[i]) 269564d8bc2SJim Ingham return NULL; 270564d8bc2SJim Ingham else 271564d8bc2SJim Ingham { 272564d8bc2SJim Ingham // Find where we are in the instruction list as well. If we aren't at an instruction, 273564d8bc2SJim Ingham // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy. 274564d8bc2SJim Ingham 275564d8bc2SJim Ingham insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); 276564d8bc2SJim Ingham if (insn_offset == UINT32_MAX) 277564d8bc2SJim Ingham return NULL; 278564d8bc2SJim Ingham else 279564d8bc2SJim Ingham { 280564d8bc2SJim Ingham range_index = i; 281564d8bc2SJim Ingham return &m_instruction_ranges[i]->GetInstructionList(); 282564d8bc2SJim Ingham } 283564d8bc2SJim Ingham } 284564d8bc2SJim Ingham } 285564d8bc2SJim Ingham } 286564d8bc2SJim Ingham return NULL; 287564d8bc2SJim Ingham } 288564d8bc2SJim Ingham 289564d8bc2SJim Ingham void 290564d8bc2SJim Ingham ThreadPlanStepRange::ClearNextBranchBreakpoint() 291564d8bc2SJim Ingham { 292564d8bc2SJim Ingham if (m_next_branch_bp_sp) 293564d8bc2SJim Ingham { 294564d8bc2SJim Ingham GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); 295564d8bc2SJim Ingham m_next_branch_bp_sp.reset(); 296564d8bc2SJim Ingham } 297564d8bc2SJim Ingham } 298564d8bc2SJim Ingham 299564d8bc2SJim Ingham bool 300564d8bc2SJim Ingham ThreadPlanStepRange::SetNextBranchBreakpoint () 301564d8bc2SJim Ingham { 302564d8bc2SJim Ingham // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction 303564d8bc2SJim Ingham // single stepping. 304564d8bc2SJim Ingham return false; 305564d8bc2SJim Ingham // Always clear the next branch breakpoint, we don't want to leave one of these stranded. 306564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 307564d8bc2SJim Ingham lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); 308564d8bc2SJim Ingham // Find the current address in our address ranges, and fetch the disassembly if we haven't already: 309564d8bc2SJim Ingham size_t pc_index; 310564d8bc2SJim Ingham size_t range_index; 311564d8bc2SJim Ingham InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); 312564d8bc2SJim Ingham if (instructions == NULL) 313564d8bc2SJim Ingham return false; 314564d8bc2SJim Ingham else 315564d8bc2SJim Ingham { 316564d8bc2SJim Ingham uint32_t branch_index; 317564d8bc2SJim Ingham branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index); 318564d8bc2SJim Ingham 319564d8bc2SJim Ingham Address run_to_address; 320564d8bc2SJim Ingham 321564d8bc2SJim Ingham // If we didn't find a branch, run to the end of the range. 322564d8bc2SJim Ingham if (branch_index == UINT32_MAX) 323564d8bc2SJim Ingham { 324564d8bc2SJim Ingham branch_index = instructions->GetSize() - 2; 325564d8bc2SJim Ingham } 326564d8bc2SJim Ingham if (branch_index - pc_index > 1) 327564d8bc2SJim Ingham { 328564d8bc2SJim Ingham const bool is_internal = true; 329564d8bc2SJim Ingham run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); 330564d8bc2SJim Ingham m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); 331564d8bc2SJim Ingham m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); 332564d8bc2SJim Ingham return true; 333564d8bc2SJim Ingham } 334564d8bc2SJim Ingham } 335564d8bc2SJim Ingham return false; 336564d8bc2SJim Ingham } 337564d8bc2SJim Ingham 338564d8bc2SJim Ingham bool 339564d8bc2SJim Ingham ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) 340564d8bc2SJim Ingham { 341564d8bc2SJim Ingham if (!m_next_branch_bp_sp) 342564d8bc2SJim Ingham return false; 343564d8bc2SJim Ingham 344564d8bc2SJim Ingham break_id_t bp_site_id = stop_info_sp->GetValue(); 345564d8bc2SJim Ingham BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); 346564d8bc2SJim Ingham if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) 347564d8bc2SJim Ingham return false; 348564d8bc2SJim Ingham else 349564d8bc2SJim Ingham return bp_site_sp->GetNumberOfOwners() == 1; 350564d8bc2SJim Ingham } 351564d8bc2SJim Ingham 352564d8bc2SJim Ingham bool 35330fdc8d8SChris Lattner ThreadPlanStepRange::WillStop () 35430fdc8d8SChris Lattner { 35530fdc8d8SChris Lattner return true; 35630fdc8d8SChris Lattner } 35730fdc8d8SChris Lattner 35830fdc8d8SChris Lattner StateType 35906e827ccSJim Ingham ThreadPlanStepRange::GetPlanRunState () 36030fdc8d8SChris Lattner { 361564d8bc2SJim Ingham if (m_next_branch_bp_sp) 362564d8bc2SJim Ingham return eStateRunning; 363564d8bc2SJim Ingham else 36430fdc8d8SChris Lattner return eStateStepping; 36530fdc8d8SChris Lattner } 36630fdc8d8SChris Lattner 36730fdc8d8SChris Lattner bool 36830fdc8d8SChris Lattner ThreadPlanStepRange::MischiefManaged () 36930fdc8d8SChris Lattner { 37030fdc8d8SChris Lattner bool done = true; 37130fdc8d8SChris Lattner if (!IsPlanComplete()) 37230fdc8d8SChris Lattner { 37330fdc8d8SChris Lattner if (InRange()) 37430fdc8d8SChris Lattner { 37530fdc8d8SChris Lattner done = false; 37630fdc8d8SChris Lattner } 377b5c0d1ccSJim Ingham else 378b5c0d1ccSJim Ingham { 379b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 380b5c0d1ccSJim Ingham if (frame_order != eFrameCompareOlder) 38130fdc8d8SChris Lattner { 38230fdc8d8SChris Lattner if (m_no_more_plans) 38330fdc8d8SChris Lattner done = true; 38430fdc8d8SChris Lattner else 38530fdc8d8SChris Lattner done = false; 38630fdc8d8SChris Lattner } 38730fdc8d8SChris Lattner else 38830fdc8d8SChris Lattner done = true; 38930fdc8d8SChris Lattner } 390b5c0d1ccSJim Ingham } 39130fdc8d8SChris Lattner 39230fdc8d8SChris Lattner if (done) 39330fdc8d8SChris Lattner { 3942d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 39530fdc8d8SChris Lattner if (log) 39630fdc8d8SChris Lattner log->Printf("Completed step through range plan."); 39730fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 39830fdc8d8SChris Lattner return true; 39930fdc8d8SChris Lattner } 40030fdc8d8SChris Lattner else 40130fdc8d8SChris Lattner { 40230fdc8d8SChris Lattner return false; 40330fdc8d8SChris Lattner } 40430fdc8d8SChris Lattner 40530fdc8d8SChris Lattner } 406*64e7ead1SJim Ingham 407*64e7ead1SJim Ingham bool 408*64e7ead1SJim Ingham ThreadPlanStepRange::IsPlanStale () 409*64e7ead1SJim Ingham { 410*64e7ead1SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 411*64e7ead1SJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 412*64e7ead1SJim Ingham 413*64e7ead1SJim Ingham if (frame_order == eFrameCompareOlder) 414*64e7ead1SJim Ingham { 415*64e7ead1SJim Ingham if (log) 416*64e7ead1SJim Ingham { 417*64e7ead1SJim Ingham log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out."); 418*64e7ead1SJim Ingham } 419*64e7ead1SJim Ingham return true; 420*64e7ead1SJim Ingham } 421*64e7ead1SJim Ingham else if (frame_order == eFrameCompareEqual && InSymbol()) 422*64e7ead1SJim Ingham { 423*64e7ead1SJim Ingham // If we are not in a place we should step through, we've gotten stale. 424*64e7ead1SJim Ingham // One tricky bit here is that some stubs don't push a frame, so we should. 425*64e7ead1SJim Ingham // check that we are in the same symbol. 426*64e7ead1SJim Ingham if (!InRange()) 427*64e7ead1SJim Ingham { 428*64e7ead1SJim Ingham return true; 429*64e7ead1SJim Ingham } 430*64e7ead1SJim Ingham } 431*64e7ead1SJim Ingham return false; 432*64e7ead1SJim Ingham } 433