1 //===-- ThreadPlanStepUntil.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 #include "lldb/Target/ThreadPlanStepUntil.h" 11 12 #include "lldb/Breakpoint/Breakpoint.h" 13 #include "lldb/Symbol/SymbolContextScope.h" 14 #include "lldb/Target/Process.h" 15 #include "lldb/Target/RegisterContext.h" 16 #include "lldb/Target/StopInfo.h" 17 #include "lldb/Target/Target.h" 18 #include "lldb/Utility/Log.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 //---------------------------------------------------------------------- 24 // ThreadPlanStepUntil: Run until we reach a given line number or step out of 25 // the current frame 26 //---------------------------------------------------------------------- 27 28 ThreadPlanStepUntil::ThreadPlanStepUntil(Thread &thread, 29 lldb::addr_t *address_list, 30 size_t num_addresses, bool stop_others, 31 uint32_t frame_idx) 32 : ThreadPlan(ThreadPlan::eKindStepUntil, "Step until", thread, 33 eVoteNoOpinion, eVoteNoOpinion), 34 m_step_from_insn(LLDB_INVALID_ADDRESS), 35 m_return_bp_id(LLDB_INVALID_BREAK_ID), 36 m_return_addr(LLDB_INVALID_ADDRESS), m_stepped_out(false), 37 m_should_stop(false), m_ran_analyze(false), m_explains_stop(false), 38 m_until_points(), m_stop_others(stop_others) { 39 // Stash away our "until" addresses: 40 TargetSP target_sp(m_thread.CalculateTarget()); 41 42 StackFrameSP frame_sp(m_thread.GetStackFrameAtIndex(frame_idx)); 43 if (frame_sp) { 44 m_step_from_insn = frame_sp->GetStackID().GetPC(); 45 lldb::user_id_t thread_id = m_thread.GetID(); 46 47 // Find the return address and set a breakpoint there: 48 // FIXME - can we do this more securely if we know first_insn? 49 50 StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1)); 51 if (return_frame_sp) { 52 // TODO: add inline functionality 53 m_return_addr = return_frame_sp->GetStackID().GetPC(); 54 Breakpoint *return_bp = 55 target_sp->CreateBreakpoint(m_return_addr, true, false).get(); 56 if (return_bp != nullptr) { 57 return_bp->SetThreadID(thread_id); 58 m_return_bp_id = return_bp->GetID(); 59 return_bp->SetBreakpointKind("until-return-backstop"); 60 } 61 } 62 63 m_stack_id = frame_sp->GetStackID(); 64 65 // Now set breakpoints on all our return addresses: 66 for (size_t i = 0; i < num_addresses; i++) { 67 Breakpoint *until_bp = 68 target_sp->CreateBreakpoint(address_list[i], true, false).get(); 69 if (until_bp != nullptr) { 70 until_bp->SetThreadID(thread_id); 71 m_until_points[address_list[i]] = until_bp->GetID(); 72 until_bp->SetBreakpointKind("until-target"); 73 } else { 74 m_until_points[address_list[i]] = LLDB_INVALID_BREAK_ID; 75 } 76 } 77 } 78 } 79 80 ThreadPlanStepUntil::~ThreadPlanStepUntil() { Clear(); } 81 82 void ThreadPlanStepUntil::Clear() { 83 TargetSP target_sp(m_thread.CalculateTarget()); 84 if (target_sp) { 85 if (m_return_bp_id != LLDB_INVALID_BREAK_ID) { 86 target_sp->RemoveBreakpointByID(m_return_bp_id); 87 m_return_bp_id = LLDB_INVALID_BREAK_ID; 88 } 89 90 until_collection::iterator pos, end = m_until_points.end(); 91 for (pos = m_until_points.begin(); pos != end; pos++) { 92 target_sp->RemoveBreakpointByID((*pos).second); 93 } 94 } 95 m_until_points.clear(); 96 } 97 98 void ThreadPlanStepUntil::GetDescription(Stream *s, 99 lldb::DescriptionLevel level) { 100 if (level == lldb::eDescriptionLevelBrief) { 101 s->Printf("step until"); 102 if (m_stepped_out) 103 s->Printf(" - stepped out"); 104 } else { 105 if (m_until_points.size() == 1) 106 s->Printf("Stepping from address 0x%" PRIx64 " until we reach 0x%" PRIx64 107 " using breakpoint %d", 108 (uint64_t)m_step_from_insn, 109 (uint64_t)(*m_until_points.begin()).first, 110 (*m_until_points.begin()).second); 111 else { 112 until_collection::iterator pos, end = m_until_points.end(); 113 s->Printf("Stepping from address 0x%" PRIx64 " until we reach one of:", 114 (uint64_t)m_step_from_insn); 115 for (pos = m_until_points.begin(); pos != end; pos++) { 116 s->Printf("\n\t0x%" PRIx64 " (bp: %d)", (uint64_t)(*pos).first, 117 (*pos).second); 118 } 119 } 120 s->Printf(" stepped out address is 0x%" PRIx64 ".", 121 (uint64_t)m_return_addr); 122 } 123 } 124 125 bool ThreadPlanStepUntil::ValidatePlan(Stream *error) { 126 if (m_return_bp_id == LLDB_INVALID_BREAK_ID) 127 return false; 128 else { 129 until_collection::iterator pos, end = m_until_points.end(); 130 for (pos = m_until_points.begin(); pos != end; pos++) { 131 if (!LLDB_BREAK_ID_IS_VALID((*pos).second)) 132 return false; 133 } 134 return true; 135 } 136 } 137 138 void ThreadPlanStepUntil::AnalyzeStop() { 139 if (m_ran_analyze) 140 return; 141 142 StopInfoSP stop_info_sp = GetPrivateStopInfo(); 143 m_should_stop = true; 144 m_explains_stop = false; 145 146 if (stop_info_sp) { 147 StopReason reason = stop_info_sp->GetStopReason(); 148 149 if (reason == eStopReasonBreakpoint) { 150 // If this is OUR breakpoint, we're fine, otherwise we don't know why 151 // this happened... 152 BreakpointSiteSP this_site = 153 m_thread.GetProcess()->GetBreakpointSiteList().FindByID( 154 stop_info_sp->GetValue()); 155 if (!this_site) { 156 m_explains_stop = false; 157 return; 158 } 159 160 if (this_site->IsBreakpointAtThisSite(m_return_bp_id)) { 161 // If we are at our "step out" breakpoint, and the stack depth has 162 // shrunk, then this is indeed our stop. If the stack depth has grown, 163 // then we've hit our step out breakpoint recursively. If we are the 164 // only breakpoint at that location, then we do explain the stop, and 165 // we'll just continue. If there was another breakpoint here, then we 166 // don't explain the stop, but we won't mark ourselves Completed, 167 // because maybe that breakpoint will continue, and then we'll finish 168 // the "until". 169 bool done; 170 StackID cur_frame_zero_id; 171 172 done = (m_stack_id < cur_frame_zero_id); 173 174 if (done) { 175 m_stepped_out = true; 176 SetPlanComplete(); 177 } else 178 m_should_stop = false; 179 180 if (this_site->GetNumberOfOwners() == 1) 181 m_explains_stop = true; 182 else 183 m_explains_stop = false; 184 return; 185 } else { 186 // Check if we've hit one of our "until" breakpoints. 187 until_collection::iterator pos, end = m_until_points.end(); 188 for (pos = m_until_points.begin(); pos != end; pos++) { 189 if (this_site->IsBreakpointAtThisSite((*pos).second)) { 190 // If we're at the right stack depth, then we're done. 191 192 bool done; 193 StackID frame_zero_id = 194 m_thread.GetStackFrameAtIndex(0)->GetStackID(); 195 196 if (frame_zero_id == m_stack_id) 197 done = true; 198 else if (frame_zero_id < m_stack_id) 199 done = false; 200 else { 201 StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1); 202 203 // But if we can't even unwind one frame we should just get out 204 // of here & stop... 205 if (older_frame_sp) { 206 const SymbolContext &older_context = 207 older_frame_sp->GetSymbolContext(eSymbolContextEverything); 208 SymbolContext stack_context; 209 m_stack_id.GetSymbolContextScope()->CalculateSymbolContext( 210 &stack_context); 211 212 done = (older_context == stack_context); 213 } else 214 done = false; 215 } 216 217 if (done) 218 SetPlanComplete(); 219 else 220 m_should_stop = false; 221 222 // Otherwise we've hit this breakpoint recursively. If we're the 223 // only breakpoint here, then we do explain the stop, and we'll 224 // continue. If not then we should let higher plans handle this 225 // stop. 226 if (this_site->GetNumberOfOwners() == 1) 227 m_explains_stop = true; 228 else { 229 m_should_stop = true; 230 m_explains_stop = false; 231 } 232 return; 233 } 234 } 235 } 236 // If we get here we haven't hit any of our breakpoints, so let the 237 // higher plans take care of the stop. 238 m_explains_stop = false; 239 return; 240 } else if (IsUsuallyUnexplainedStopReason(reason)) { 241 m_explains_stop = false; 242 } else { 243 m_explains_stop = true; 244 } 245 } 246 } 247 248 bool ThreadPlanStepUntil::DoPlanExplainsStop(Event *event_ptr) { 249 // We don't explain signals or breakpoints (breakpoints that handle stepping 250 // in or out will be handled by a child plan. 251 AnalyzeStop(); 252 return m_explains_stop; 253 } 254 255 bool ThreadPlanStepUntil::ShouldStop(Event *event_ptr) { 256 // If we've told our self in ExplainsStop that we plan to continue, then do 257 // so here. Otherwise, as long as this thread has stopped for a reason, we 258 // will stop. 259 260 StopInfoSP stop_info_sp = GetPrivateStopInfo(); 261 if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone) 262 return false; 263 264 AnalyzeStop(); 265 return m_should_stop; 266 } 267 268 bool ThreadPlanStepUntil::StopOthers() { return m_stop_others; } 269 270 StateType ThreadPlanStepUntil::GetPlanRunState() { return eStateRunning; } 271 272 bool ThreadPlanStepUntil::DoWillResume(StateType resume_state, 273 bool current_plan) { 274 if (current_plan) { 275 TargetSP target_sp(m_thread.CalculateTarget()); 276 if (target_sp) { 277 Breakpoint *return_bp = 278 target_sp->GetBreakpointByID(m_return_bp_id).get(); 279 if (return_bp != nullptr) 280 return_bp->SetEnabled(true); 281 282 until_collection::iterator pos, end = m_until_points.end(); 283 for (pos = m_until_points.begin(); pos != end; pos++) { 284 Breakpoint *until_bp = 285 target_sp->GetBreakpointByID((*pos).second).get(); 286 if (until_bp != nullptr) 287 until_bp->SetEnabled(true); 288 } 289 } 290 } 291 292 m_should_stop = true; 293 m_ran_analyze = false; 294 m_explains_stop = false; 295 return true; 296 } 297 298 bool ThreadPlanStepUntil::WillStop() { 299 TargetSP target_sp(m_thread.CalculateTarget()); 300 if (target_sp) { 301 Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get(); 302 if (return_bp != nullptr) 303 return_bp->SetEnabled(false); 304 305 until_collection::iterator pos, end = m_until_points.end(); 306 for (pos = m_until_points.begin(); pos != end; pos++) { 307 Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get(); 308 if (until_bp != nullptr) 309 until_bp->SetEnabled(false); 310 } 311 } 312 return true; 313 } 314 315 bool ThreadPlanStepUntil::MischiefManaged() { 316 // I'm letting "PlanExplainsStop" do all the work, and just reporting that 317 // here. 318 bool done = false; 319 if (IsPlanComplete()) { 320 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 321 if (log) 322 log->Printf("Completed step until plan."); 323 324 Clear(); 325 done = true; 326 } 327 if (done) 328 ThreadPlan::MischiefManaged(); 329 330 return done; 331 } 332