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 36*242e0ad7SJim Ingham ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, 37*242e0ad7SJim Ingham const char *name, 38*242e0ad7SJim Ingham Thread &thread, 39*242e0ad7SJim Ingham const AddressRange &range, 40*242e0ad7SJim Ingham const SymbolContext &addr_context, 41*242e0ad7SJim Ingham lldb::RunMode stop_others) : 4235b21fefSJim Ingham ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion), 4330fdc8d8SChris Lattner m_addr_context (addr_context), 44c982c768SGreg Clayton m_address_range (range), 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 { 5130fdc8d8SChris Lattner m_stack_depth = m_thread.GetStackFrameCount(); 5230fdc8d8SChris Lattner m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 5330fdc8d8SChris Lattner } 5430fdc8d8SChris Lattner 5530fdc8d8SChris Lattner ThreadPlanStepRange::~ThreadPlanStepRange () 5630fdc8d8SChris Lattner { 5730fdc8d8SChris Lattner } 5830fdc8d8SChris Lattner 5930fdc8d8SChris Lattner bool 6030fdc8d8SChris Lattner ThreadPlanStepRange::ValidatePlan (Stream *error) 6130fdc8d8SChris Lattner { 6230fdc8d8SChris Lattner return true; 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner 6530fdc8d8SChris Lattner bool 6630fdc8d8SChris Lattner ThreadPlanStepRange::PlanExplainsStop () 6730fdc8d8SChris Lattner { 6830fdc8d8SChris Lattner // We don't explain signals or breakpoints (breakpoints that handle stepping in or 6930fdc8d8SChris Lattner // out will be handled by a child plan. 70b15bfc75SJim Ingham StopInfoSP stop_info_sp = GetPrivateStopReason(); 71b15bfc75SJim Ingham if (stop_info_sp) 7230fdc8d8SChris Lattner { 73b15bfc75SJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 7430fdc8d8SChris Lattner 7530fdc8d8SChris Lattner switch (reason) 7630fdc8d8SChris Lattner { 7730fdc8d8SChris Lattner case eStopReasonBreakpoint: 7830fdc8d8SChris Lattner case eStopReasonWatchpoint: 7930fdc8d8SChris Lattner case eStopReasonSignal: 8030fdc8d8SChris Lattner case eStopReasonException: 8130fdc8d8SChris Lattner return false; 8230fdc8d8SChris Lattner default: 8330fdc8d8SChris Lattner return true; 8430fdc8d8SChris Lattner } 8530fdc8d8SChris Lattner } 8630fdc8d8SChris Lattner return true; 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 8930fdc8d8SChris Lattner Vote 9030fdc8d8SChris Lattner ThreadPlanStepRange::ShouldReportStop (Event *event_ptr) 9130fdc8d8SChris Lattner { 922d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 932cad65a5SGreg Clayton 942cad65a5SGreg Clayton const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo; 952cad65a5SGreg Clayton if (log) 96411c0ce8SGreg Clayton log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote); 972cad65a5SGreg Clayton return vote; 9830fdc8d8SChris Lattner } 9930fdc8d8SChris Lattner 10030fdc8d8SChris Lattner bool 10130fdc8d8SChris Lattner ThreadPlanStepRange::InRange () 10230fdc8d8SChris Lattner { 1032d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 10430fdc8d8SChris Lattner bool ret_value = false; 10530fdc8d8SChris Lattner 10630fdc8d8SChris Lattner lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 10730fdc8d8SChris Lattner 108f5e56de0SGreg Clayton ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess().GetTarget()); 10930fdc8d8SChris Lattner 11030fdc8d8SChris Lattner if (!ret_value) 11130fdc8d8SChris Lattner { 11230fdc8d8SChris Lattner // See if we've just stepped to another part of the same line number... 11330fdc8d8SChris Lattner StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 11430fdc8d8SChris Lattner 11530fdc8d8SChris Lattner SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 11630fdc8d8SChris Lattner if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 11730fdc8d8SChris Lattner { 11830fdc8d8SChris Lattner if ((m_addr_context.line_entry.file == new_context.line_entry.file) 11930fdc8d8SChris Lattner && (m_addr_context.line_entry.line == new_context.line_entry.line)) 12030fdc8d8SChris Lattner { 12130fdc8d8SChris Lattner m_addr_context = new_context; 12230fdc8d8SChris Lattner m_address_range = m_addr_context.line_entry.range; 12330fdc8d8SChris Lattner ret_value = true; 12430fdc8d8SChris Lattner if (log) 12530fdc8d8SChris Lattner { 12630fdc8d8SChris Lattner StreamString s; 127f5e56de0SGreg Clayton m_address_range.Dump (&s, &m_thread.GetProcess().GetTarget(), Address::DumpStyleLoadAddress); 12830fdc8d8SChris Lattner 12930fdc8d8SChris Lattner log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner } 13230fdc8d8SChris Lattner } 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner } 13530fdc8d8SChris Lattner 13630fdc8d8SChris Lattner if (!ret_value && log) 13730fdc8d8SChris Lattner log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr); 13830fdc8d8SChris Lattner 13930fdc8d8SChris Lattner return ret_value; 14030fdc8d8SChris Lattner } 14130fdc8d8SChris Lattner 14230fdc8d8SChris Lattner bool 14330fdc8d8SChris Lattner ThreadPlanStepRange::InSymbol() 14430fdc8d8SChris Lattner { 14530fdc8d8SChris Lattner lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 14630fdc8d8SChris Lattner if (m_addr_context.function != NULL) 14730fdc8d8SChris Lattner { 148f5e56de0SGreg Clayton return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget()); 14930fdc8d8SChris Lattner } 15030fdc8d8SChris Lattner else if (m_addr_context.symbol != NULL) 15130fdc8d8SChris Lattner { 152f5e56de0SGreg Clayton return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, &m_thread.GetProcess().GetTarget()); 15330fdc8d8SChris Lattner } 15430fdc8d8SChris Lattner return false; 15530fdc8d8SChris Lattner } 15630fdc8d8SChris Lattner 15730fdc8d8SChris Lattner // FIXME: This should also handle inlining if we aren't going to do inlining in the 15830fdc8d8SChris Lattner // main stack. 15930fdc8d8SChris Lattner // 16030fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that 16130fdc8d8SChris Lattner // to the current list. 16230fdc8d8SChris Lattner 16330fdc8d8SChris Lattner bool 16430fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsYounger () 16530fdc8d8SChris Lattner { 1662d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 1677ce490c6SJim Ingham 1687ce490c6SJim Ingham // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above 1697ce490c6SJim Ingham // us on the stack. Counting the whole stack could be expensive. 1707ce490c6SJim Ingham 17130fdc8d8SChris Lattner uint32_t current_depth = m_thread.GetStackFrameCount(); 17230fdc8d8SChris Lattner if (current_depth == m_stack_depth) 17330fdc8d8SChris Lattner { 17430fdc8d8SChris Lattner if (log) 17530fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger still in start function."); 17630fdc8d8SChris Lattner return false; 17730fdc8d8SChris Lattner } 17830fdc8d8SChris Lattner else if (current_depth < m_stack_depth) 17930fdc8d8SChris Lattner { 18030fdc8d8SChris Lattner if (log) 18130fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 18230fdc8d8SChris Lattner return false; 18330fdc8d8SChris Lattner } 18430fdc8d8SChris Lattner else 18530fdc8d8SChris Lattner { 18630fdc8d8SChris Lattner if (log) 18730fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 18830fdc8d8SChris Lattner return true; 18930fdc8d8SChris Lattner } 19030fdc8d8SChris Lattner } 19130fdc8d8SChris Lattner 19230fdc8d8SChris Lattner bool 19330fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsOlder () 19430fdc8d8SChris Lattner { 1952d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 19630fdc8d8SChris Lattner uint32_t current_depth = m_thread.GetStackFrameCount(); 19730fdc8d8SChris Lattner if (current_depth == m_stack_depth) 19830fdc8d8SChris Lattner { 19930fdc8d8SChris Lattner if (log) 20030fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder still in start function."); 20130fdc8d8SChris Lattner return false; 20230fdc8d8SChris Lattner } 20330fdc8d8SChris Lattner else if (current_depth < m_stack_depth) 20430fdc8d8SChris Lattner { 20530fdc8d8SChris Lattner if (log) 20630fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 20730fdc8d8SChris Lattner return true; 20830fdc8d8SChris Lattner } 20930fdc8d8SChris Lattner else 21030fdc8d8SChris Lattner { 21130fdc8d8SChris Lattner if (log) 21230fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 21330fdc8d8SChris Lattner return false; 21430fdc8d8SChris Lattner } 21530fdc8d8SChris Lattner } 21630fdc8d8SChris Lattner 21730fdc8d8SChris Lattner bool 21830fdc8d8SChris Lattner ThreadPlanStepRange::StopOthers () 21930fdc8d8SChris Lattner { 22030fdc8d8SChris Lattner if (m_stop_others == lldb::eOnlyThisThread 22130fdc8d8SChris Lattner || m_stop_others == lldb::eOnlyDuringStepping) 22230fdc8d8SChris Lattner return true; 22330fdc8d8SChris Lattner else 22430fdc8d8SChris Lattner return false; 22530fdc8d8SChris Lattner } 22630fdc8d8SChris Lattner 22730fdc8d8SChris Lattner bool 22830fdc8d8SChris Lattner ThreadPlanStepRange::WillStop () 22930fdc8d8SChris Lattner { 23030fdc8d8SChris Lattner return true; 23130fdc8d8SChris Lattner } 23230fdc8d8SChris Lattner 23330fdc8d8SChris Lattner StateType 23406e827ccSJim Ingham ThreadPlanStepRange::GetPlanRunState () 23530fdc8d8SChris Lattner { 23630fdc8d8SChris Lattner return eStateStepping; 23730fdc8d8SChris Lattner } 23830fdc8d8SChris Lattner 23930fdc8d8SChris Lattner bool 24030fdc8d8SChris Lattner ThreadPlanStepRange::MischiefManaged () 24130fdc8d8SChris Lattner { 24230fdc8d8SChris Lattner bool done = true; 24330fdc8d8SChris Lattner if (!IsPlanComplete()) 24430fdc8d8SChris Lattner { 24530fdc8d8SChris Lattner if (InRange()) 24630fdc8d8SChris Lattner { 24730fdc8d8SChris Lattner done = false; 24830fdc8d8SChris Lattner } 24930fdc8d8SChris Lattner else if (!FrameIsOlder()) 25030fdc8d8SChris Lattner { 25130fdc8d8SChris Lattner if (m_no_more_plans) 25230fdc8d8SChris Lattner done = true; 25330fdc8d8SChris Lattner else 25430fdc8d8SChris Lattner done = false; 25530fdc8d8SChris Lattner } 25630fdc8d8SChris Lattner else 25730fdc8d8SChris Lattner done = true; 25830fdc8d8SChris Lattner } 25930fdc8d8SChris Lattner 26030fdc8d8SChris Lattner if (done) 26130fdc8d8SChris Lattner { 2622d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 26330fdc8d8SChris Lattner if (log) 26430fdc8d8SChris Lattner log->Printf("Completed step through range plan."); 26530fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 26630fdc8d8SChris Lattner return true; 26730fdc8d8SChris Lattner } 26830fdc8d8SChris Lattner else 26930fdc8d8SChris Lattner { 27030fdc8d8SChris Lattner return false; 27130fdc8d8SChris Lattner } 27230fdc8d8SChris Lattner 27330fdc8d8SChris Lattner } 274