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