1 //===-- ThreadPlanStepInstruction.cpp ---------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 11 #include "lldb/Target/ThreadPlanStepInstruction.h" 12 13 // C Includes 14 // C++ Includes 15 // Other libraries and framework includes 16 // Project includes 17 #include "lldb/lldb-private-log.h" 18 #include "lldb/Core/Log.h" 19 #include "lldb/Core/Stream.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/RegisterContext.h" 22 #include "lldb/Target/RegisterContext.h" 23 #include "lldb/Target/StopInfo.h" 24 #include "lldb/Target/Target.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 //---------------------------------------------------------------------- 30 // ThreadPlanStepInstruction: Step over the current instruction 31 //---------------------------------------------------------------------- 32 33 ThreadPlanStepInstruction::ThreadPlanStepInstruction 34 ( 35 Thread &thread, 36 bool step_over, 37 bool stop_other_threads, 38 Vote stop_vote, 39 Vote run_vote 40 ) : 41 ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote), 42 m_instruction_addr (0), 43 m_stop_other_threads (stop_other_threads), 44 m_step_over (step_over) 45 { 46 m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0); 47 m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 48 } 49 50 ThreadPlanStepInstruction::~ThreadPlanStepInstruction () 51 { 52 } 53 54 void 55 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level) 56 { 57 if (level == lldb::eDescriptionLevelBrief) 58 { 59 if (m_step_over) 60 s->Printf ("instruction step over"); 61 else 62 s->Printf ("instruction step into"); 63 } 64 else 65 { 66 s->Printf ("Stepping one instruction past "); 67 s->Address(m_instruction_addr, sizeof (addr_t)); 68 if (m_step_over) 69 s->Printf(" stepping over calls"); 70 else 71 s->Printf(" stepping into calls"); 72 } 73 } 74 75 bool 76 ThreadPlanStepInstruction::ValidatePlan (Stream *error) 77 { 78 // Since we read the instruction we're stepping over from the thread, 79 // this plan will always work. 80 return true; 81 } 82 83 bool 84 ThreadPlanStepInstruction::PlanExplainsStop () 85 { 86 StopInfoSP stop_info_sp = GetPrivateStopReason(); 87 if (stop_info_sp) 88 { 89 StopReason reason = stop_info_sp->GetStopReason(); 90 if (reason == eStopReasonTrace || reason == eStopReasonNone) 91 return true; 92 else 93 return false; 94 } 95 return false; 96 } 97 98 bool 99 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) 100 { 101 if (m_step_over) 102 { 103 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 104 105 StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 106 107 if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) 108 { 109 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 110 { 111 SetPlanComplete(); 112 return true; 113 } 114 else 115 return false; 116 } 117 else 118 { 119 // We've stepped in, step back out again: 120 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get(); 121 if (return_frame) 122 { 123 if (log) 124 { 125 StreamString s; 126 s.PutCString ("Stepped in to: "); 127 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 128 s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 129 s.PutCString (" stepping out to: "); 130 addr_t return_addr = return_frame->GetRegisterContext()->GetPC(); 131 s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 132 log->Printf("%s.", s.GetData()); 133 } 134 m_thread.QueueThreadPlanForStepOut(false, 135 NULL, 136 true, 137 m_stop_other_threads, 138 eVoteNo, 139 eVoteNoOpinion, 140 0); 141 return false; 142 } 143 else 144 { 145 if (log) 146 log->Printf("Could not find previous frame, stopping."); 147 SetPlanComplete(); 148 return true; 149 } 150 151 } 152 153 } 154 else 155 { 156 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 157 { 158 SetPlanComplete(); 159 return true; 160 } 161 else 162 return false; 163 } 164 } 165 166 bool 167 ThreadPlanStepInstruction::StopOthers () 168 { 169 return m_stop_other_threads; 170 } 171 172 StateType 173 ThreadPlanStepInstruction::GetPlanRunState () 174 { 175 return eStateStepping; 176 } 177 178 bool 179 ThreadPlanStepInstruction::WillStop () 180 { 181 return true; 182 } 183 184 bool 185 ThreadPlanStepInstruction::MischiefManaged () 186 { 187 if (IsPlanComplete()) 188 { 189 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 190 if (log) 191 log->Printf("Completed single instruction step plan."); 192 ThreadPlan::MischiefManaged (); 193 return true; 194 } 195 else 196 { 197 return false; 198 } 199 } 200 201