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 Target &target = m_thread.GetProcess().GetTarget(); 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.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.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 Target &target = m_thread.GetProcess().GetTarget(); 110 if (m_return_bp_id != LLDB_INVALID_BREAK_ID) 111 { 112 target.RemoveBreakpointByID(m_return_bp_id); 113 m_return_bp_id = LLDB_INVALID_BREAK_ID; 114 } 115 116 until_collection::iterator pos, end = m_until_points.end(); 117 for (pos = m_until_points.begin(); pos != end; pos++) 118 { 119 target.RemoveBreakpointByID((*pos).second); 120 } 121 m_until_points.clear(); 122 } 123 124 void 125 ThreadPlanStepUntil::GetDescription (Stream *s, lldb::DescriptionLevel level) 126 { 127 if (level == lldb::eDescriptionLevelBrief) 128 { 129 s->Printf ("step until"); 130 if (m_stepped_out) 131 s->Printf (" - stepped out"); 132 } 133 else 134 { 135 if (m_until_points.size() == 1) 136 s->Printf ("Stepping from address 0x%llx until we reach 0x%llx using breakpoint %d", 137 (uint64_t)m_step_from_insn, 138 (uint64_t) (*m_until_points.begin()).first, 139 (*m_until_points.begin()).second); 140 else 141 { 142 until_collection::iterator pos, end = m_until_points.end(); 143 s->Printf ("Stepping from address 0x%llx until we reach one of:", 144 (uint64_t)m_step_from_insn); 145 for (pos = m_until_points.begin(); pos != end; pos++) 146 { 147 s->Printf ("\n\t0x%llx (bp: %d)", (uint64_t) (*pos).first, (*pos).second); 148 } 149 } 150 s->Printf(" stepped out address is 0x%llx.", (uint64_t) m_return_addr); 151 } 152 } 153 154 bool 155 ThreadPlanStepUntil::ValidatePlan (Stream *error) 156 { 157 if (m_return_bp_id == LLDB_INVALID_BREAK_ID) 158 return false; 159 else 160 { 161 until_collection::iterator pos, end = m_until_points.end(); 162 for (pos = m_until_points.begin(); pos != end; pos++) 163 { 164 if (!LLDB_BREAK_ID_IS_VALID ((*pos).second)) 165 return false; 166 } 167 return true; 168 } 169 } 170 171 void 172 ThreadPlanStepUntil::AnalyzeStop() 173 { 174 if (m_ran_analyze) 175 return; 176 177 StopInfoSP stop_info_sp = GetPrivateStopReason(); 178 m_should_stop = true; 179 m_explains_stop = false; 180 181 if (stop_info_sp) 182 { 183 StopReason reason = stop_info_sp->GetStopReason(); 184 185 switch (reason) 186 { 187 case eStopReasonBreakpoint: 188 { 189 // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened... 190 BreakpointSiteSP this_site = m_thread.GetProcess().GetBreakpointSiteList().FindByID (stop_info_sp->GetValue()); 191 if (!this_site) 192 { 193 m_explains_stop = false; 194 return; 195 } 196 197 if (this_site->IsBreakpointAtThisSite (m_return_bp_id)) 198 { 199 // If we are at our "step out" breakpoint, and the stack depth has shrunk, then 200 // this is indeed our stop. 201 // If the stack depth has grown, then we've hit our step out breakpoint recursively. 202 // If we are the only breakpoint at that location, then we do explain the stop, and 203 // we'll just continue. 204 // If there was another breakpoint here, then we don't explain the stop, but we won't 205 // mark ourselves Completed, because maybe that breakpoint will continue, and then 206 // we'll finish the "until". 207 if (m_stack_depth > m_thread.GetStackFrameCount()) 208 { 209 m_stepped_out = true; 210 SetPlanComplete(); 211 } 212 else 213 m_should_stop = false; 214 215 if (this_site->GetNumberOfOwners() == 1) 216 m_explains_stop = true; 217 else 218 m_explains_stop = false; 219 return; 220 } 221 else 222 { 223 // Check if we've hit one of our "until" breakpoints. 224 until_collection::iterator pos, end = m_until_points.end(); 225 for (pos = m_until_points.begin(); pos != end; pos++) 226 { 227 if (this_site->IsBreakpointAtThisSite ((*pos).second)) 228 { 229 // If we're at the right stack depth, then we're done. 230 if (m_stack_depth == m_thread.GetStackFrameCount()) 231 SetPlanComplete(); 232 else 233 m_should_stop = false; 234 235 // Otherwise we've hit this breakpoint recursively. If we're the 236 // only breakpoint here, then we do explain the stop, and we'll continue. 237 // If not then we should let higher plans handle this stop. 238 if (this_site->GetNumberOfOwners() == 1) 239 m_explains_stop = true; 240 else 241 { 242 m_should_stop = true; 243 m_explains_stop = false; 244 } 245 return; 246 } 247 } 248 } 249 // If we get here we haven't hit any of our breakpoints, so let the higher 250 // plans take care of the stop. 251 m_explains_stop = false; 252 return; 253 } 254 case eStopReasonWatchpoint: 255 case eStopReasonSignal: 256 case eStopReasonException: 257 m_explains_stop = false; 258 break; 259 default: 260 m_explains_stop = true; 261 break; 262 } 263 } 264 } 265 266 bool 267 ThreadPlanStepUntil::PlanExplainsStop () 268 { 269 // We don't explain signals or breakpoints (breakpoints that handle stepping in or 270 // out will be handled by a child plan. 271 AnalyzeStop(); 272 return m_explains_stop; 273 } 274 275 bool 276 ThreadPlanStepUntil::ShouldStop (Event *event_ptr) 277 { 278 // If we've told our self in ExplainsStop that we plan to continue, then 279 // do so here. Otherwise, as long as this thread has stopped for a reason, 280 // we will stop. 281 282 StopInfoSP stop_info_sp = GetPrivateStopReason(); 283 if (stop_info_sp == NULL || stop_info_sp->GetStopReason() == eStopReasonNone) 284 return false; 285 286 AnalyzeStop(); 287 return m_should_stop; 288 } 289 290 bool 291 ThreadPlanStepUntil::StopOthers () 292 { 293 return m_stop_others; 294 } 295 296 StateType 297 ThreadPlanStepUntil::GetPlanRunState () 298 { 299 return eStateRunning; 300 } 301 302 bool 303 ThreadPlanStepUntil::WillResume (StateType resume_state, bool current_plan) 304 { 305 ThreadPlan::WillResume (resume_state, current_plan); 306 if (current_plan) 307 { 308 Target &target = m_thread.GetProcess().GetTarget(); 309 Breakpoint *return_bp = target.GetBreakpointByID(m_return_bp_id).get(); 310 if (return_bp != NULL) 311 return_bp->SetEnabled (true); 312 313 until_collection::iterator pos, end = m_until_points.end(); 314 for (pos = m_until_points.begin(); pos != end; pos++) 315 { 316 Breakpoint *until_bp = target.GetBreakpointByID((*pos).second).get(); 317 if (until_bp != NULL) 318 until_bp->SetEnabled (true); 319 } 320 } 321 322 m_should_stop = true; 323 m_ran_analyze = false; 324 m_explains_stop = false; 325 return true; 326 } 327 328 bool 329 ThreadPlanStepUntil::WillStop () 330 { 331 Target &target = m_thread.GetProcess().GetTarget(); 332 Breakpoint *return_bp = target.GetBreakpointByID(m_return_bp_id).get(); 333 if (return_bp != NULL) 334 return_bp->SetEnabled (false); 335 336 until_collection::iterator pos, end = m_until_points.end(); 337 for (pos = m_until_points.begin(); pos != end; pos++) 338 { 339 Breakpoint *until_bp = target.GetBreakpointByID((*pos).second).get(); 340 if (until_bp != NULL) 341 until_bp->SetEnabled (false); 342 } 343 return true; 344 } 345 346 bool 347 ThreadPlanStepUntil::MischiefManaged () 348 { 349 350 // I'm letting "PlanExplainsStop" do all the work, and just reporting that here. 351 bool done = false; 352 if (IsPlanComplete()) 353 { 354 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 355 if (log) 356 log->Printf("Completed step until plan."); 357 358 Clear(); 359 done = true; 360 } 361 if (done) 362 ThreadPlan::MischiefManaged (); 363 364 return done; 365 366 } 367 368