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