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 26using namespace lldb; 27using namespace lldb_private; 28 29//---------------------------------------------------------------------- 30// ThreadPlanStepInstruction: Step over the current instruction 31//---------------------------------------------------------------------- 32 33ThreadPlanStepInstruction::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 57ThreadPlanStepInstruction::~ThreadPlanStepInstruction () 58{ 59} 60 61void 62ThreadPlanStepInstruction::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 85bool 86ThreadPlanStepInstruction::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 93bool 94ThreadPlanStepInstruction::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 108bool 109ThreadPlanStepInstruction::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 193bool 194ThreadPlanStepInstruction::StopOthers () 195{ 196 return m_stop_other_threads; 197} 198 199StateType 200ThreadPlanStepInstruction::GetPlanRunState () 201{ 202 return eStateStepping; 203} 204 205bool 206ThreadPlanStepInstruction::WillStop () 207{ 208 return true; 209} 210 211bool 212ThreadPlanStepInstruction::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