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