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/Core/Log.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Target/RegisterContext.h" 21 #include "lldb/Target/RegisterContext.h" 22 #include "lldb/Target/StopInfo.h" 23 #include "lldb/Target/Target.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 //---------------------------------------------------------------------- 29 // ThreadPlanStepInstruction: Step over the current instruction 30 //---------------------------------------------------------------------- 31 32 ThreadPlanStepInstruction::ThreadPlanStepInstruction 33 ( 34 Thread &thread, 35 bool step_over, 36 bool stop_other_threads, 37 Vote stop_vote, 38 Vote run_vote 39 ) : 40 ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote), 41 m_instruction_addr (0), 42 m_stop_other_threads (stop_other_threads), 43 m_step_over (step_over) 44 { 45 m_takes_iteration_count = true; 46 SetUpState(); 47 } 48 49 ThreadPlanStepInstruction::~ThreadPlanStepInstruction () 50 { 51 } 52 53 void 54 ThreadPlanStepInstruction::SetUpState() 55 { 56 m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0); 57 StackFrameSP start_frame_sp(m_thread.GetStackFrameAtIndex(0)); 58 m_stack_id = start_frame_sp->GetStackID(); 59 60 m_start_has_symbol = start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL; 61 62 StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1); 63 if (parent_frame_sp) 64 m_parent_frame_id = parent_frame_sp->GetStackID(); 65 } 66 67 void 68 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level) 69 { 70 if (level == lldb::eDescriptionLevelBrief) 71 { 72 if (m_step_over) 73 s->Printf ("instruction step over"); 74 else 75 s->Printf ("instruction step into"); 76 } 77 else 78 { 79 s->Printf ("Stepping one instruction past "); 80 s->Address(m_instruction_addr, sizeof (addr_t)); 81 if (!m_start_has_symbol) 82 s->Printf(" which has no symbol"); 83 84 if (m_step_over) 85 s->Printf(" stepping over calls"); 86 else 87 s->Printf(" stepping into calls"); 88 } 89 } 90 91 bool 92 ThreadPlanStepInstruction::ValidatePlan (Stream *error) 93 { 94 // Since we read the instruction we're stepping over from the thread, 95 // this plan will always work. 96 return true; 97 } 98 99 bool 100 ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr) 101 { 102 StopInfoSP stop_info_sp = GetPrivateStopInfo (); 103 if (stop_info_sp) 104 { 105 StopReason reason = stop_info_sp->GetStopReason(); 106 if (reason == eStopReasonTrace || reason == eStopReasonNone) 107 return true; 108 else 109 return false; 110 } 111 return false; 112 } 113 114 bool 115 ThreadPlanStepInstruction::IsPlanStale () 116 { 117 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 118 StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 119 if (cur_frame_id == m_stack_id) 120 { 121 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 122 return true; 123 else 124 return false; 125 } 126 else if (cur_frame_id < m_stack_id) 127 { 128 // If the current frame is younger than the start frame and we are stepping over, then we need to continue, 129 // but if we are doing just one step, we're done. 130 if (m_step_over) 131 return false; 132 else 133 return true; 134 } 135 else 136 { 137 if (log) 138 { 139 log->Printf ("ThreadPlanStepInstruction::IsPlanStale - Current frame is older than start frame, plan is stale."); 140 } 141 return true; 142 } 143 } 144 145 bool 146 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) 147 { 148 if (m_step_over) 149 { 150 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 151 152 StackFrameSP cur_frame_sp = m_thread.GetStackFrameAtIndex(0); 153 if (!cur_frame_sp) 154 { 155 if (log) 156 log->Printf ("ThreadPlanStepInstruction couldn't get the 0th frame, stopping."); 157 SetPlanComplete(); 158 return true; 159 } 160 161 StackID cur_frame_zero_id = cur_frame_sp->GetStackID(); 162 163 if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) 164 { 165 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 166 { 167 if (--m_iteration_count <= 0) 168 { 169 SetPlanComplete(); 170 return true; 171 } 172 else 173 { 174 // We are still stepping, reset the start pc, and in case we've stepped out, 175 // reset the current stack id. 176 SetUpState(); 177 return false; 178 } 179 } 180 else 181 return false; 182 } 183 else 184 { 185 // We've stepped in, step back out again: 186 StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get(); 187 if (return_frame) 188 { 189 if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol) 190 { 191 // next-instruction shouldn't step out of inlined functions. But we may have stepped into a 192 // real function that starts with an inlined function, and we do want to step out of that... 193 194 if (cur_frame_sp->IsInlined()) 195 { 196 StackFrameSP parent_frame_sp = m_thread.GetFrameWithStackID(m_stack_id); 197 198 if(parent_frame_sp && parent_frame_sp->GetConcreteFrameIndex() == cur_frame_sp->GetConcreteFrameIndex()) 199 { 200 SetPlanComplete(); 201 if (log) 202 { 203 log->Printf("Frame we stepped into is inlined into the frame we were stepping from, stopping."); 204 } 205 return true; 206 } 207 } 208 209 if (log) 210 { 211 StreamString s; 212 s.PutCString ("Stepped in to: "); 213 addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 214 s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 215 s.PutCString (" stepping out to: "); 216 addr_t return_addr = return_frame->GetRegisterContext()->GetPC(); 217 s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 218 log->Printf("%s.", s.GetData()); 219 } 220 221 // StepInstruction should probably have the tri-state RunMode, but for now it is safer to 222 // run others. 223 const bool stop_others = false; 224 m_thread.QueueThreadPlanForStepOutNoShouldStop(false, 225 NULL, 226 true, 227 stop_others, 228 eVoteNo, 229 eVoteNoOpinion, 230 0); 231 return false; 232 } 233 else 234 { 235 if (log) 236 { 237 log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols. " 238 "We are probably just confused about where we are, stopping."); 239 } 240 SetPlanComplete(); 241 return true; 242 } 243 } 244 else 245 { 246 if (log) 247 log->Printf("Could not find previous frame, stopping."); 248 SetPlanComplete(); 249 return true; 250 } 251 252 } 253 254 } 255 else 256 { 257 if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) 258 { 259 if (--m_iteration_count <= 0) 260 { 261 SetPlanComplete(); 262 return true; 263 } 264 else 265 { 266 // We are still stepping, reset the start pc, and in case we've stepped in or out, 267 // reset the current stack id. 268 SetUpState(); 269 return false; 270 } 271 } 272 else 273 return false; 274 } 275 } 276 277 bool 278 ThreadPlanStepInstruction::StopOthers () 279 { 280 return m_stop_other_threads; 281 } 282 283 StateType 284 ThreadPlanStepInstruction::GetPlanRunState () 285 { 286 return eStateStepping; 287 } 288 289 bool 290 ThreadPlanStepInstruction::WillStop () 291 { 292 return true; 293 } 294 295 bool 296 ThreadPlanStepInstruction::MischiefManaged () 297 { 298 if (IsPlanComplete()) 299 { 300 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 301 if (log) 302 log->Printf("Completed single instruction step plan."); 303 ThreadPlan::MischiefManaged (); 304 return true; 305 } 306 else 307 { 308 return false; 309 } 310 } 311 312