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