130fdc8d8SChris Lattner //===-- ThreadPlanStepInstruction.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 1130fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInstruction.h" 1230fdc8d8SChris Lattner 1330fdc8d8SChris Lattner // C Includes 1430fdc8d8SChris Lattner // C++ Includes 1530fdc8d8SChris Lattner // Other libraries and framework includes 1630fdc8d8SChris Lattner // Project includes 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/Target/Process.h" 21f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h" 22f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h" 23f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h" 24f4b47e15SGreg Clayton #include "lldb/Target/Target.h" 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner using namespace lldb; 2730fdc8d8SChris Lattner using namespace lldb_private; 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 3030fdc8d8SChris Lattner // ThreadPlanStepInstruction: Step over the current instruction 3130fdc8d8SChris Lattner //---------------------------------------------------------------------- 3230fdc8d8SChris Lattner 3330fdc8d8SChris Lattner ThreadPlanStepInstruction::ThreadPlanStepInstruction 3430fdc8d8SChris Lattner ( 3530fdc8d8SChris Lattner Thread &thread, 3630fdc8d8SChris Lattner bool step_over, 3730fdc8d8SChris Lattner bool stop_other_threads, 3830fdc8d8SChris Lattner Vote stop_vote, 3930fdc8d8SChris Lattner Vote run_vote 4030fdc8d8SChris Lattner ) : 41b01e742aSJim Ingham ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote), 4230fdc8d8SChris Lattner m_instruction_addr (0), 431ee0d4f7SBenjamin Kramer m_stop_other_threads (stop_other_threads), 446b35c86fSJim Ingham m_step_over (step_over) 451ee0d4f7SBenjamin Kramer { 46*7a88ec9aSJim Ingham m_takes_iteration_count = true; 47*7a88ec9aSJim Ingham SetUpState(); 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner 5030fdc8d8SChris Lattner ThreadPlanStepInstruction::~ThreadPlanStepInstruction () 5130fdc8d8SChris Lattner { 5230fdc8d8SChris Lattner } 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner void 55*7a88ec9aSJim Ingham ThreadPlanStepInstruction::SetUpState() 56*7a88ec9aSJim Ingham { 57*7a88ec9aSJim Ingham m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0); 58*7a88ec9aSJim Ingham StackFrameSP start_frame_sp(m_thread.GetStackFrameAtIndex(0)); 59*7a88ec9aSJim Ingham m_stack_id = start_frame_sp->GetStackID(); 60*7a88ec9aSJim Ingham 61*7a88ec9aSJim Ingham m_start_has_symbol = start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL; 62*7a88ec9aSJim Ingham 63*7a88ec9aSJim Ingham StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1); 64*7a88ec9aSJim Ingham if (parent_frame_sp) 65*7a88ec9aSJim Ingham m_parent_frame_id = parent_frame_sp->GetStackID(); 66*7a88ec9aSJim Ingham } 67*7a88ec9aSJim Ingham 68*7a88ec9aSJim Ingham void 6930fdc8d8SChris Lattner ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level) 7030fdc8d8SChris Lattner { 7130fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 7230fdc8d8SChris Lattner { 7330fdc8d8SChris Lattner if (m_step_over) 7430fdc8d8SChris Lattner s->Printf ("instruction step over"); 7530fdc8d8SChris Lattner else 7630fdc8d8SChris Lattner s->Printf ("instruction step into"); 7730fdc8d8SChris Lattner } 7830fdc8d8SChris Lattner else 7930fdc8d8SChris Lattner { 8030fdc8d8SChris Lattner s->Printf ("Stepping one instruction past "); 8130fdc8d8SChris Lattner s->Address(m_instruction_addr, sizeof (addr_t)); 82a7d4822cSJim Ingham if (!m_start_has_symbol) 83a7d4822cSJim Ingham s->Printf(" which has no symbol"); 84a7d4822cSJim Ingham 8530fdc8d8SChris Lattner if (m_step_over) 8630fdc8d8SChris Lattner s->Printf(" stepping over calls"); 8730fdc8d8SChris Lattner else 8830fdc8d8SChris Lattner s->Printf(" stepping into calls"); 8930fdc8d8SChris Lattner } 9030fdc8d8SChris Lattner } 9130fdc8d8SChris Lattner 9230fdc8d8SChris Lattner bool 9330fdc8d8SChris Lattner ThreadPlanStepInstruction::ValidatePlan (Stream *error) 9430fdc8d8SChris Lattner { 9530fdc8d8SChris Lattner // Since we read the instruction we're stepping over from the thread, 9630fdc8d8SChris Lattner // this plan will always work. 9730fdc8d8SChris Lattner return true; 9830fdc8d8SChris Lattner } 9930fdc8d8SChris Lattner 10030fdc8d8SChris Lattner bool 101221d51cfSJim Ingham ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr) 10230fdc8d8SChris Lattner { 10360c4118cSJim Ingham StopInfoSP stop_info_sp = GetPrivateStopInfo (); 104b15bfc75SJim Ingham if (stop_info_sp) 10530fdc8d8SChris Lattner { 106b15bfc75SJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 10730fdc8d8SChris Lattner if (reason == eStopReasonTrace || reason == eStopReasonNone) 10830fdc8d8SChris Lattner return true; 10930fdc8d8SChris Lattner else 11030fdc8d8SChris Lattner return false; 11130fdc8d8SChris Lattner } 11230fdc8d8SChris Lattner return false; 11330fdc8d8SChris Lattner } 11430fdc8d8SChris Lattner 11530fdc8d8SChris Lattner bool 116*7a88ec9aSJim Ingham ThreadPlanStepInstruction::IsPlanStale () 117*7a88ec9aSJim Ingham { 118*7a88ec9aSJim Ingham Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 119*7a88ec9aSJim Ingham StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 120*7a88ec9aSJim Ingham if (cur_frame_id == m_stack_id) 121*7a88ec9aSJim Ingham { 122*7a88ec9aSJim Ingham if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 123*7a88ec9aSJim Ingham return true; 124*7a88ec9aSJim Ingham else 125*7a88ec9aSJim Ingham return false; 126*7a88ec9aSJim Ingham } 127*7a88ec9aSJim Ingham else if (cur_frame_id < m_stack_id) 128*7a88ec9aSJim Ingham { 129*7a88ec9aSJim Ingham // If the current frame is younger than the start frame and we are stepping over, then we need to continue, 130*7a88ec9aSJim Ingham // but if we are doing just one step, we're done. 131*7a88ec9aSJim Ingham if (m_step_over) 132*7a88ec9aSJim Ingham return false; 133*7a88ec9aSJim Ingham else 134*7a88ec9aSJim Ingham return true; 135*7a88ec9aSJim Ingham } 136*7a88ec9aSJim Ingham else 137*7a88ec9aSJim Ingham { 138*7a88ec9aSJim Ingham if (log) 139*7a88ec9aSJim Ingham { 140*7a88ec9aSJim Ingham log->Printf ("ThreadPlanStepInstruction::IsPlanStale - Current frame is older than start frame, plan is stale."); 141*7a88ec9aSJim Ingham } 142*7a88ec9aSJim Ingham return true; 143*7a88ec9aSJim Ingham } 144*7a88ec9aSJim Ingham } 145*7a88ec9aSJim Ingham 146*7a88ec9aSJim Ingham bool 14730fdc8d8SChris Lattner ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) 14830fdc8d8SChris Lattner { 14930fdc8d8SChris Lattner if (m_step_over) 15030fdc8d8SChris Lattner { 1515160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 1526b35c86fSJim Ingham 1536b35c86fSJim Ingham StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 1546b35c86fSJim Ingham 1556b35c86fSJim Ingham if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) 15630fdc8d8SChris Lattner { 15730fdc8d8SChris Lattner if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 15830fdc8d8SChris Lattner { 159*7a88ec9aSJim Ingham if (--m_iteration_count <= 0) 160*7a88ec9aSJim Ingham { 16130fdc8d8SChris Lattner SetPlanComplete(); 16230fdc8d8SChris Lattner return true; 16330fdc8d8SChris Lattner } 16430fdc8d8SChris Lattner else 165*7a88ec9aSJim Ingham { 166*7a88ec9aSJim Ingham // We are still stepping, reset the start pc, and in case we've stepped out, 167*7a88ec9aSJim Ingham // reset the current stack id. 168*7a88ec9aSJim Ingham SetUpState(); 169*7a88ec9aSJim Ingham return false; 170*7a88ec9aSJim Ingham } 171*7a88ec9aSJim Ingham } 172*7a88ec9aSJim Ingham else 17330fdc8d8SChris Lattner return false; 17430fdc8d8SChris Lattner } 17530fdc8d8SChris Lattner else 17630fdc8d8SChris Lattner { 17730fdc8d8SChris Lattner // We've stepped in, step back out again: 178b57e4a1bSJason Molenda StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get(); 17930fdc8d8SChris Lattner if (return_frame) 18030fdc8d8SChris Lattner { 181a7d4822cSJim Ingham if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol) 182886a3e2cSJim Ingham { 18330fdc8d8SChris Lattner if (log) 18430fdc8d8SChris Lattner { 18530fdc8d8SChris Lattner StreamString s; 18630fdc8d8SChris Lattner s.PutCString ("Stepped in to: "); 1879da7bd07SGreg Clayton addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 1881ac04c30SGreg Clayton s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 18930fdc8d8SChris Lattner s.PutCString (" stepping out to: "); 1909da7bd07SGreg Clayton addr_t return_addr = return_frame->GetRegisterContext()->GetPC(); 1911ac04c30SGreg Clayton s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 19230fdc8d8SChris Lattner log->Printf("%s.", s.GetData()); 19330fdc8d8SChris Lattner } 1944a58e968SJim Ingham 1954a58e968SJim Ingham // StepInstruction should probably have the tri-state RunMode, but for now it is safer to 1964a58e968SJim Ingham // run others. 1974a58e968SJim Ingham const bool stop_others = false; 1984b4b2478SJim Ingham m_thread.QueueThreadPlanForStepOutNoShouldStop(false, 19964e7ead1SJim Ingham NULL, 20064e7ead1SJim Ingham true, 2014a58e968SJim Ingham stop_others, 20264e7ead1SJim Ingham eVoteNo, 20364e7ead1SJim Ingham eVoteNoOpinion, 20464e7ead1SJim Ingham 0); 20530fdc8d8SChris Lattner return false; 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner else 20830fdc8d8SChris Lattner { 20930fdc8d8SChris Lattner if (log) 210886a3e2cSJim Ingham { 211a7d4822cSJim Ingham log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols. " 212886a3e2cSJim Ingham "We are probably just confused about where we are, stopping."); 213886a3e2cSJim Ingham } 214886a3e2cSJim Ingham SetPlanComplete(); 215886a3e2cSJim Ingham return true; 216886a3e2cSJim Ingham } 217886a3e2cSJim Ingham } 218886a3e2cSJim Ingham else 219886a3e2cSJim Ingham { 220886a3e2cSJim Ingham if (log) 22130fdc8d8SChris Lattner log->Printf("Could not find previous frame, stopping."); 22230fdc8d8SChris Lattner SetPlanComplete(); 22330fdc8d8SChris Lattner return true; 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner } 22730fdc8d8SChris Lattner 22830fdc8d8SChris Lattner } 22930fdc8d8SChris Lattner else 23030fdc8d8SChris Lattner { 23130fdc8d8SChris Lattner if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 23230fdc8d8SChris Lattner { 233*7a88ec9aSJim Ingham if (--m_iteration_count <= 0) 234*7a88ec9aSJim Ingham { 23530fdc8d8SChris Lattner SetPlanComplete(); 23630fdc8d8SChris Lattner return true; 23730fdc8d8SChris Lattner } 23830fdc8d8SChris Lattner else 239*7a88ec9aSJim Ingham { 240*7a88ec9aSJim Ingham // We are still stepping, reset the start pc, and in case we've stepped in or out, 241*7a88ec9aSJim Ingham // reset the current stack id. 242*7a88ec9aSJim Ingham SetUpState(); 243*7a88ec9aSJim Ingham return false; 244*7a88ec9aSJim Ingham } 245*7a88ec9aSJim Ingham } 246*7a88ec9aSJim Ingham else 24730fdc8d8SChris Lattner return false; 24830fdc8d8SChris Lattner } 24930fdc8d8SChris Lattner } 25030fdc8d8SChris Lattner 25130fdc8d8SChris Lattner bool 25230fdc8d8SChris Lattner ThreadPlanStepInstruction::StopOthers () 25330fdc8d8SChris Lattner { 25430fdc8d8SChris Lattner return m_stop_other_threads; 25530fdc8d8SChris Lattner } 25630fdc8d8SChris Lattner 25730fdc8d8SChris Lattner StateType 25806e827ccSJim Ingham ThreadPlanStepInstruction::GetPlanRunState () 25930fdc8d8SChris Lattner { 26030fdc8d8SChris Lattner return eStateStepping; 26130fdc8d8SChris Lattner } 26230fdc8d8SChris Lattner 26330fdc8d8SChris Lattner bool 26430fdc8d8SChris Lattner ThreadPlanStepInstruction::WillStop () 26530fdc8d8SChris Lattner { 26630fdc8d8SChris Lattner return true; 26730fdc8d8SChris Lattner } 26830fdc8d8SChris Lattner 26930fdc8d8SChris Lattner bool 27030fdc8d8SChris Lattner ThreadPlanStepInstruction::MischiefManaged () 27130fdc8d8SChris Lattner { 27230fdc8d8SChris Lattner if (IsPlanComplete()) 27330fdc8d8SChris Lattner { 2745160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 27530fdc8d8SChris Lattner if (log) 27630fdc8d8SChris Lattner log->Printf("Completed single instruction step plan."); 27730fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 27830fdc8d8SChris Lattner return true; 27930fdc8d8SChris Lattner } 28030fdc8d8SChris Lattner else 28130fdc8d8SChris Lattner { 28230fdc8d8SChris Lattner return false; 28330fdc8d8SChris Lattner } 28430fdc8d8SChris Lattner } 28530fdc8d8SChris Lattner 286