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 StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0)); 48 m_stack_id = m_start_frame_sp->GetStackID(); 49 50 m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL; 51 52 StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1); 53 if (parent_frame_sp) 54 m_parent_frame_id = parent_frame_sp->GetStackID(); 55 } 56 57 ThreadPlanStepInstruction::~ThreadPlanStepInstruction () 58 { 59 } 60 61 void 62 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level) 63 { 64 if (level == lldb::eDescriptionLevelBrief) 65 { 66 if (m_step_over) 67 s->Printf ("instruction step over"); 68 else 69 s->Printf ("instruction step into"); 70 } 71 else 72 { 73 s->Printf ("Stepping one instruction past "); 74 s->Address(m_instruction_addr, sizeof (addr_t)); 75 if (!m_start_has_symbol) 76 s->Printf(" which has no symbol"); 77 78 if (m_step_over) 79 s->Printf(" stepping over calls"); 80 else 81 s->Printf(" stepping into calls"); 82 } 83 } 84 85 bool 86 ThreadPlanStepInstruction::ValidatePlan (Stream *error) 87 { 88 // Since we read the instruction we're stepping over from the thread, 89 // this plan will always work. 90 return true; 91 } 92 93 bool 94 ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr) 95 { 96 StopInfoSP stop_info_sp = GetPrivateStopInfo (); 97 if (stop_info_sp) 98 { 99 StopReason reason = stop_info_sp->GetStopReason(); 100 if (reason == eStopReasonTrace || reason == eStopReasonNone) 101 return true; 102 else 103 return false; 104 } 105 return false; 106 } 107 108 bool 109 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) 110 { 111 if (m_step_over) 112 { 113 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 114 115 StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 116 117 if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) 118 { 119 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 120 { 121 SetPlanComplete(); 122 return true; 123 } 124 else 125 return false; 126 } 127 else 128 { 129 // We've stepped in, step back out again: 130 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get(); 131 if (return_frame) 132 { 133 if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol) 134 { 135 if (log) 136 { 137 StreamString s; 138 s.PutCString ("Stepped in to: "); 139 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 140 s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 141 s.PutCString (" stepping out to: "); 142 addr_t return_addr = return_frame->GetRegisterContext()->GetPC(); 143 s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 144 log->Printf("%s.", s.GetData()); 145 } 146 147 // StepInstruction should probably have the tri-state RunMode, but for now it is safer to 148 // run others. 149 const bool stop_others = false; 150 m_thread.QueueThreadPlanForStepOut(false, 151 NULL, 152 true, 153 stop_others, 154 eVoteNo, 155 eVoteNoOpinion, 156 0); 157 return false; 158 } 159 else 160 { 161 if (log) 162 { 163 log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols. " 164 "We are probably just confused about where we are, stopping."); 165 } 166 SetPlanComplete(); 167 return true; 168 } 169 } 170 else 171 { 172 if (log) 173 log->Printf("Could not find previous frame, stopping."); 174 SetPlanComplete(); 175 return true; 176 } 177 178 } 179 180 } 181 else 182 { 183 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 184 { 185 SetPlanComplete(); 186 return true; 187 } 188 else 189 return false; 190 } 191 } 192 193 bool 194 ThreadPlanStepInstruction::StopOthers () 195 { 196 return m_stop_other_threads; 197 } 198 199 StateType 200 ThreadPlanStepInstruction::GetPlanRunState () 201 { 202 return eStateStepping; 203 } 204 205 bool 206 ThreadPlanStepInstruction::WillStop () 207 { 208 return true; 209 } 210 211 bool 212 ThreadPlanStepInstruction::MischiefManaged () 213 { 214 if (IsPlanComplete()) 215 { 216 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 217 if (log) 218 log->Printf("Completed single instruction step plan."); 219 ThreadPlan::MischiefManaged (); 220 return true; 221 } 222 else 223 { 224 return false; 225 } 226 } 227 228