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" 1830fdc8d8SChris Lattner #include "lldb/Core/Log.h" 1930fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 2030fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 2130fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 22f4b47e15SGreg Clayton #include "lldb/Target/Process.h" 23f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h" 24f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h" 25f4b47e15SGreg Clayton #include "lldb/Target/Thread.h" 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner using namespace lldb; 2830fdc8d8SChris Lattner using namespace lldb_private; 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner //---------------------------------------------------------------------- 3230fdc8d8SChris Lattner // ThreadPlanStepRange: Step through a stack range, either stepping over or into 3330fdc8d8SChris Lattner // based on the value of \a type. 3430fdc8d8SChris Lattner //---------------------------------------------------------------------- 3530fdc8d8SChris Lattner 36242e0ad7SJim Ingham ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, 37242e0ad7SJim Ingham const char *name, 38242e0ad7SJim Ingham Thread &thread, 39242e0ad7SJim Ingham const AddressRange &range, 40242e0ad7SJim Ingham const SymbolContext &addr_context, 41242e0ad7SJim Ingham lldb::RunMode stop_others) : 4235b21fefSJim Ingham ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 4330fdc8d8SChris Lattner m_addr_context (addr_context), 44*c4c9fedcSJim Ingham m_address_ranges (), 4530fdc8d8SChris Lattner m_stop_others (stop_others), 4630fdc8d8SChris Lattner m_stack_depth (0), 4730fdc8d8SChris Lattner m_stack_id (), 48c982c768SGreg Clayton m_no_more_plans (false), 4930fdc8d8SChris Lattner m_first_run_event (true) 5030fdc8d8SChris Lattner { 51*c4c9fedcSJim Ingham AddRange(range); 5230fdc8d8SChris Lattner m_stack_depth = m_thread.GetStackFrameCount(); 5330fdc8d8SChris Lattner m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 5430fdc8d8SChris Lattner } 5530fdc8d8SChris Lattner 5630fdc8d8SChris Lattner ThreadPlanStepRange::~ThreadPlanStepRange () 5730fdc8d8SChris Lattner { 5830fdc8d8SChris Lattner } 5930fdc8d8SChris Lattner 6030fdc8d8SChris Lattner bool 6130fdc8d8SChris Lattner ThreadPlanStepRange::ValidatePlan (Stream *error) 6230fdc8d8SChris Lattner { 6330fdc8d8SChris Lattner return true; 6430fdc8d8SChris Lattner } 6530fdc8d8SChris Lattner 6630fdc8d8SChris Lattner bool 6730fdc8d8SChris Lattner ThreadPlanStepRange::PlanExplainsStop () 6830fdc8d8SChris Lattner { 6930fdc8d8SChris Lattner // We don't explain signals or breakpoints (breakpoints that handle stepping in or 7030fdc8d8SChris Lattner // out will be handled by a child plan. 71b15bfc75SJim Ingham StopInfoSP stop_info_sp = GetPrivateStopReason(); 72b15bfc75SJim Ingham if (stop_info_sp) 7330fdc8d8SChris Lattner { 74b15bfc75SJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 7530fdc8d8SChris Lattner 7630fdc8d8SChris Lattner switch (reason) 7730fdc8d8SChris Lattner { 7830fdc8d8SChris Lattner case eStopReasonBreakpoint: 7930fdc8d8SChris Lattner case eStopReasonWatchpoint: 8030fdc8d8SChris Lattner case eStopReasonSignal: 8130fdc8d8SChris Lattner case eStopReasonException: 8230fdc8d8SChris Lattner return false; 8330fdc8d8SChris Lattner default: 8430fdc8d8SChris Lattner return true; 8530fdc8d8SChris Lattner } 8630fdc8d8SChris Lattner } 8730fdc8d8SChris Lattner return true; 8830fdc8d8SChris Lattner } 8930fdc8d8SChris Lattner 9030fdc8d8SChris Lattner Vote 9130fdc8d8SChris Lattner ThreadPlanStepRange::ShouldReportStop (Event *event_ptr) 9230fdc8d8SChris Lattner { 932d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 942cad65a5SGreg Clayton 952cad65a5SGreg Clayton const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 962cad65a5SGreg Clayton if (log) 97411c0ce8SGreg Clayton log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote); 982cad65a5SGreg Clayton return vote; 9930fdc8d8SChris Lattner } 10030fdc8d8SChris Lattner 101*c4c9fedcSJim Ingham void 102*c4c9fedcSJim Ingham ThreadPlanStepRange::AddRange(const AddressRange &new_range) 103*c4c9fedcSJim Ingham { 104*c4c9fedcSJim Ingham // For now I'm just adding the ranges. At some point we may want to 105*c4c9fedcSJim Ingham // condense the ranges if they overlap, though I don't think it is likely 106*c4c9fedcSJim Ingham // to be very important. 107*c4c9fedcSJim Ingham m_address_ranges.push_back (new_range); 108*c4c9fedcSJim Ingham } 109*c4c9fedcSJim Ingham 110*c4c9fedcSJim Ingham void 111*c4c9fedcSJim Ingham ThreadPlanStepRange::DumpRanges(Stream *s) 112*c4c9fedcSJim Ingham { 113*c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 114*c4c9fedcSJim Ingham if (num_ranges == 1) 115*c4c9fedcSJim Ingham { 116*c4c9fedcSJim Ingham m_address_ranges[0].Dump (s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress); 117*c4c9fedcSJim Ingham } 118*c4c9fedcSJim Ingham else 119*c4c9fedcSJim Ingham { 120*c4c9fedcSJim Ingham for (size_t i = 0; i < num_ranges; i++) 121*c4c9fedcSJim Ingham { 122*c4c9fedcSJim Ingham s->PutCString("%d: "); 123*c4c9fedcSJim Ingham m_address_ranges[i].Dump (s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress); 124*c4c9fedcSJim Ingham } 125*c4c9fedcSJim Ingham } 126*c4c9fedcSJim Ingham } 127*c4c9fedcSJim Ingham 12830fdc8d8SChris Lattner bool 12930fdc8d8SChris Lattner ThreadPlanStepRange::InRange () 13030fdc8d8SChris Lattner { 1312d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 13230fdc8d8SChris Lattner bool ret_value = false; 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 13530fdc8d8SChris Lattner 136*c4c9fedcSJim Ingham size_t num_ranges = m_address_ranges.size(); 137*c4c9fedcSJim Ingham for (size_t i = 0; i < num_ranges; i++) 138*c4c9fedcSJim Ingham { 139*c4c9fedcSJim Ingham ret_value = m_address_ranges[i].ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess().GetTarget()); 140*c4c9fedcSJim Ingham if (ret_value) 141*c4c9fedcSJim Ingham break; 142*c4c9fedcSJim Ingham } 14330fdc8d8SChris Lattner 14430fdc8d8SChris Lattner if (!ret_value) 14530fdc8d8SChris Lattner { 14630fdc8d8SChris Lattner // See if we've just stepped to another part of the same line number... 14730fdc8d8SChris Lattner StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 14830fdc8d8SChris Lattner 14930fdc8d8SChris Lattner SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 15030fdc8d8SChris Lattner if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 15130fdc8d8SChris Lattner { 152843bfb2cSJim Ingham if (m_addr_context.line_entry.file == new_context.line_entry.file) 153843bfb2cSJim Ingham { 154843bfb2cSJim Ingham if (m_addr_context.line_entry.line == new_context.line_entry.line) 15530fdc8d8SChris Lattner { 15630fdc8d8SChris Lattner m_addr_context = new_context; 157*c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 15830fdc8d8SChris Lattner ret_value = true; 15930fdc8d8SChris Lattner if (log) 16030fdc8d8SChris Lattner { 16130fdc8d8SChris Lattner StreamString s; 162*c4c9fedcSJim Ingham m_addr_context.line_entry.range.Dump (&s, 163*c4c9fedcSJim Ingham &m_thread.GetProcess().GetTarget(), 164*c4c9fedcSJim Ingham Address::DumpStyleLoadAddress); 16530fdc8d8SChris Lattner 16630fdc8d8SChris Lattner log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 16730fdc8d8SChris Lattner } 16830fdc8d8SChris Lattner } 169843bfb2cSJim Ingham else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(&m_thread.GetProcess().GetTarget()) 170843bfb2cSJim Ingham != pc_load_addr) 171843bfb2cSJim Ingham { 172843bfb2cSJim Ingham // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another 173843bfb2cSJim Ingham // line. So far I mostly see this due to bugs in the debug information. 174843bfb2cSJim Ingham // But we probably don't want to be in the middle of a line range, so in that case reset the stepping 175843bfb2cSJim Ingham // range to the line we've stepped into the middle of and continue. 176843bfb2cSJim Ingham m_addr_context = new_context; 177*c4c9fedcSJim Ingham m_address_ranges.clear(); 178*c4c9fedcSJim Ingham AddRange(m_addr_context.line_entry.range); 179843bfb2cSJim Ingham ret_value = true; 180843bfb2cSJim Ingham if (log) 181843bfb2cSJim Ingham { 182843bfb2cSJim Ingham StreamString s; 183*c4c9fedcSJim Ingham m_addr_context.line_entry.range.Dump (&s, 184*c4c9fedcSJim Ingham &m_thread.GetProcess().GetTarget(), 185*c4c9fedcSJim Ingham Address::DumpStyleLoadAddress); 186843bfb2cSJim Ingham 187843bfb2cSJim Ingham log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.", 188843bfb2cSJim Ingham new_context.line_entry.line, 189843bfb2cSJim Ingham s.GetData()); 190843bfb2cSJim Ingham } 191843bfb2cSJim Ingham 192843bfb2cSJim Ingham } 193843bfb2cSJim Ingham } 194843bfb2cSJim Ingham 19530fdc8d8SChris Lattner } 19630fdc8d8SChris Lattner 19730fdc8d8SChris Lattner } 19830fdc8d8SChris Lattner 19930fdc8d8SChris Lattner if (!ret_value && log) 20030fdc8d8SChris Lattner log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr); 20130fdc8d8SChris Lattner 20230fdc8d8SChris Lattner return ret_value; 20330fdc8d8SChris Lattner } 20430fdc8d8SChris Lattner 20530fdc8d8SChris Lattner bool 20630fdc8d8SChris Lattner ThreadPlanStepRange::InSymbol() 20730fdc8d8SChris Lattner { 20830fdc8d8SChris Lattner lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 20930fdc8d8SChris Lattner if (m_addr_context.function != NULL) 21030fdc8d8SChris Lattner { 211f5e56de0SGreg Clayton return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget()); 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner else if (m_addr_context.symbol != NULL) 21430fdc8d8SChris Lattner { 215f5e56de0SGreg Clayton return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget()); 21630fdc8d8SChris Lattner } 21730fdc8d8SChris Lattner return false; 21830fdc8d8SChris Lattner } 21930fdc8d8SChris Lattner 22030fdc8d8SChris Lattner // FIXME: This should also handle inlining if we aren't going to do inlining in the 22130fdc8d8SChris Lattner // main stack. 22230fdc8d8SChris Lattner // 22330fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that 22430fdc8d8SChris Lattner // to the current list. 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner bool 22730fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsYounger () 22830fdc8d8SChris Lattner { 2292d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 2307ce490c6SJim Ingham 2317ce490c6SJim Ingham // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above 2327ce490c6SJim Ingham // us on the stack. Counting the whole stack could be expensive. 2337ce490c6SJim Ingham 23430fdc8d8SChris Lattner uint32_t current_depth = m_thread.GetStackFrameCount(); 23530fdc8d8SChris Lattner if (current_depth == m_stack_depth) 23630fdc8d8SChris Lattner { 23730fdc8d8SChris Lattner if (log) 23830fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger still in start function."); 23930fdc8d8SChris Lattner return false; 24030fdc8d8SChris Lattner } 24130fdc8d8SChris Lattner else if (current_depth < m_stack_depth) 24230fdc8d8SChris Lattner { 24330fdc8d8SChris Lattner if (log) 24430fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 24530fdc8d8SChris Lattner return false; 24630fdc8d8SChris Lattner } 24730fdc8d8SChris Lattner else 24830fdc8d8SChris Lattner { 24930fdc8d8SChris Lattner if (log) 25030fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 25130fdc8d8SChris Lattner return true; 25230fdc8d8SChris Lattner } 25330fdc8d8SChris Lattner } 25430fdc8d8SChris Lattner 25530fdc8d8SChris Lattner bool 25630fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsOlder () 25730fdc8d8SChris Lattner { 2582d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 25930fdc8d8SChris Lattner uint32_t current_depth = m_thread.GetStackFrameCount(); 26030fdc8d8SChris Lattner if (current_depth == m_stack_depth) 26130fdc8d8SChris Lattner { 26230fdc8d8SChris Lattner if (log) 26330fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder still in start function."); 26430fdc8d8SChris Lattner return false; 26530fdc8d8SChris Lattner } 26630fdc8d8SChris Lattner else if (current_depth < m_stack_depth) 26730fdc8d8SChris Lattner { 26830fdc8d8SChris Lattner if (log) 26930fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 27030fdc8d8SChris Lattner return true; 27130fdc8d8SChris Lattner } 27230fdc8d8SChris Lattner else 27330fdc8d8SChris Lattner { 27430fdc8d8SChris Lattner if (log) 27530fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 27630fdc8d8SChris Lattner return false; 27730fdc8d8SChris Lattner } 27830fdc8d8SChris Lattner } 27930fdc8d8SChris Lattner 28030fdc8d8SChris Lattner bool 28130fdc8d8SChris Lattner ThreadPlanStepRange::StopOthers () 28230fdc8d8SChris Lattner { 28330fdc8d8SChris Lattner if (m_stop_others == lldb::eOnlyThisThread 28430fdc8d8SChris Lattner || m_stop_others == lldb::eOnlyDuringStepping) 28530fdc8d8SChris Lattner return true; 28630fdc8d8SChris Lattner else 28730fdc8d8SChris Lattner return false; 28830fdc8d8SChris Lattner } 28930fdc8d8SChris Lattner 29030fdc8d8SChris Lattner bool 29130fdc8d8SChris Lattner ThreadPlanStepRange::WillStop () 29230fdc8d8SChris Lattner { 29330fdc8d8SChris Lattner return true; 29430fdc8d8SChris Lattner } 29530fdc8d8SChris Lattner 29630fdc8d8SChris Lattner StateType 29706e827ccSJim Ingham ThreadPlanStepRange::GetPlanRunState () 29830fdc8d8SChris Lattner { 29930fdc8d8SChris Lattner return eStateStepping; 30030fdc8d8SChris Lattner } 30130fdc8d8SChris Lattner 30230fdc8d8SChris Lattner bool 30330fdc8d8SChris Lattner ThreadPlanStepRange::MischiefManaged () 30430fdc8d8SChris Lattner { 30530fdc8d8SChris Lattner bool done = true; 30630fdc8d8SChris Lattner if (!IsPlanComplete()) 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner if (InRange()) 30930fdc8d8SChris Lattner { 31030fdc8d8SChris Lattner done = false; 31130fdc8d8SChris Lattner } 31230fdc8d8SChris Lattner else if (!FrameIsOlder()) 31330fdc8d8SChris Lattner { 31430fdc8d8SChris Lattner if (m_no_more_plans) 31530fdc8d8SChris Lattner done = true; 31630fdc8d8SChris Lattner else 31730fdc8d8SChris Lattner done = false; 31830fdc8d8SChris Lattner } 31930fdc8d8SChris Lattner else 32030fdc8d8SChris Lattner done = true; 32130fdc8d8SChris Lattner } 32230fdc8d8SChris Lattner 32330fdc8d8SChris Lattner if (done) 32430fdc8d8SChris Lattner { 3252d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 32630fdc8d8SChris Lattner if (log) 32730fdc8d8SChris Lattner log->Printf("Completed step through range plan."); 32830fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 32930fdc8d8SChris Lattner return true; 33030fdc8d8SChris Lattner } 33130fdc8d8SChris Lattner else 33230fdc8d8SChris Lattner { 33330fdc8d8SChris Lattner return false; 33430fdc8d8SChris Lattner } 33530fdc8d8SChris Lattner 33630fdc8d8SChris Lattner } 337