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 (Event *event_ptr) 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 Log *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 135 // StepInstruction should probably have the tri-state RunMode, but for now it is safer to 136 // run others. 137 const bool stop_others = false; 138 m_thread.QueueThreadPlanForStepOut(false, 139 NULL, 140 true, 141 stop_others, 142 eVoteNo, 143 eVoteNoOpinion, 144 0); 145 return false; 146 } 147 else 148 { 149 if (log) 150 log->Printf("Could not find previous frame, stopping."); 151 SetPlanComplete(); 152 return true; 153 } 154 155 } 156 157 } 158 else 159 { 160 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 161 { 162 SetPlanComplete(); 163 return true; 164 } 165 else 166 return false; 167 } 168 } 169 170 bool 171 ThreadPlanStepInstruction::StopOthers () 172 { 173 return m_stop_other_threads; 174 } 175 176 StateType 177 ThreadPlanStepInstruction::GetPlanRunState () 178 { 179 return eStateStepping; 180 } 181 182 bool 183 ThreadPlanStepInstruction::WillStop () 184 { 185 return true; 186 } 187 188 bool 189 ThreadPlanStepInstruction::MischiefManaged () 190 { 191 if (IsPlanComplete()) 192 { 193 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 194 if (log) 195 log->Printf("Completed single instruction step plan."); 196 ThreadPlan::MischiefManaged (); 197 return true; 198 } 199 else 200 { 201 return false; 202 } 203 } 204 205