1 //===-- ThreadPlanStepOverBreakpoint.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 10 #include "lldb/Target/ThreadPlanStepOverBreakpoint.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/lldb-private-log.h" 17 #include "lldb/Core/Log.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Target/RegisterContext.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 25 //---------------------------------------------------------------------- 26 // ThreadPlanStepOverBreakpoint: Single steps over a breakpoint bp_site_sp at the pc. 27 //---------------------------------------------------------------------- 28 29 ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) : 30 ThreadPlan (ThreadPlan::eKindStepOverBreakpoint, "Step over breakpoint trap", 31 thread, 32 eVoteNo, 33 eVoteNoOpinion), // We need to report the run since this happens 34 // first in the thread plan stack when stepping 35 // over a breakpoint 36 m_breakpoint_addr (LLDB_INVALID_ADDRESS), 37 m_auto_continue(false), 38 m_reenabled_breakpoint_site (false) 39 40 { 41 m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC(); 42 m_breakpoint_site_id = m_thread.GetProcess()->GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr); 43 } 44 45 ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint () 46 { 47 } 48 49 void 50 ThreadPlanStepOverBreakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level) 51 { 52 s->Printf("Single stepping past breakpoint site %" PRIu64 " at 0x%" PRIx64, m_breakpoint_site_id, (uint64_t)m_breakpoint_addr); 53 } 54 55 bool 56 ThreadPlanStepOverBreakpoint::ValidatePlan (Stream *error) 57 { 58 return true; 59 } 60 61 bool 62 ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr) 63 { 64 StopInfoSP stop_info_sp = GetPrivateStopInfo (); 65 if (stop_info_sp) 66 { 67 // It's a little surprising that we stop here for a breakpoint hit. However, when you single step ONTO a breakpoint 68 // we still want to call that a breakpoint hit, and trigger the actions, etc. Otherwise you would see the 69 // PC at the breakpoint without having triggered the actions, then you'd continue, the PC wouldn't change, 70 // and you'd see the breakpoint hit, which would be odd. 71 // So the lower levels fake "step onto breakpoint address" and return that as a breakpoint. So our trace 72 // step COULD appear as a breakpoint hit if the next instruction also contained a breakpoint. 73 StopReason reason = stop_info_sp->GetStopReason(); 74 75 switch (reason) 76 { 77 case eStopReasonTrace: 78 case eStopReasonNone: 79 return true; 80 case eStopReasonBreakpoint: 81 // It's a little surprising that we stop here for a breakpoint hit. However, when you single step ONTO a 82 // breakpoint we still want to call that a breakpoint hit, and trigger the actions, etc. Otherwise you 83 // would see the PC at the breakpoint without having triggered the actions, then you'd continue, the PC 84 // wouldn't change, and you'd see the breakpoint hit, which would be odd. 85 // So the lower levels fake "step onto breakpoint address" and return that as a breakpoint hit. So our trace 86 // step COULD appear as a breakpoint hit if the next instruction also contained a breakpoint. We don't want 87 // to handle that, since we really don't know what to do with breakpoint hits. But make sure we don't set 88 // ourselves to auto-continue or we'll wrench control away from the plans that can deal with this. 89 SetAutoContinue(false); 90 return false; 91 default: 92 return false; 93 } 94 } 95 return false; 96 } 97 98 bool 99 ThreadPlanStepOverBreakpoint::ShouldStop (Event *event_ptr) 100 { 101 return !ShouldAutoContinue(event_ptr); 102 } 103 104 bool 105 ThreadPlanStepOverBreakpoint::StopOthers () 106 { 107 return true; 108 } 109 110 StateType 111 ThreadPlanStepOverBreakpoint::GetPlanRunState () 112 { 113 return eStateStepping; 114 } 115 116 bool 117 ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current_plan) 118 { 119 if (current_plan) 120 { 121 BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr)); 122 if (bp_site_sp && bp_site_sp->IsEnabled()) 123 m_thread.GetProcess()->DisableBreakpointSite (bp_site_sp.get()); 124 } 125 return true; 126 } 127 128 bool 129 ThreadPlanStepOverBreakpoint::WillStop () 130 { 131 ReenableBreakpointSite (); 132 return true; 133 } 134 135 bool 136 ThreadPlanStepOverBreakpoint::MischiefManaged () 137 { 138 lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC(); 139 140 if (pc_addr == m_breakpoint_addr) 141 { 142 // If we are still at the PC of our breakpoint, then for some reason we didn't 143 // get a chance to run. 144 return false; 145 } 146 else 147 { 148 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 149 if (log) 150 log->Printf("Completed step over breakpoint plan."); 151 // Otherwise, re-enable the breakpoint we were stepping over, and we're done. 152 ReenableBreakpointSite (); 153 ThreadPlan::MischiefManaged (); 154 return true; 155 } 156 } 157 158 void 159 ThreadPlanStepOverBreakpoint::ReenableBreakpointSite () 160 { 161 if (!m_reenabled_breakpoint_site) 162 { 163 m_reenabled_breakpoint_site = true; 164 BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr)); 165 if (bp_site_sp) 166 { 167 m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get()); 168 } 169 } 170 } 171 void 172 ThreadPlanStepOverBreakpoint::ThreadDestroyed () 173 { 174 ReenableBreakpointSite (); 175 } 176 177 void 178 ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it) 179 { 180 m_auto_continue = do_it; 181 } 182 183 bool 184 ThreadPlanStepOverBreakpoint::ShouldAutoContinue (Event *event_ptr) 185 { 186 return m_auto_continue; 187 } 188 189 bool 190 ThreadPlanStepOverBreakpoint::IsPlanStale() 191 { 192 return m_thread.GetRegisterContext()->GetPC() != m_breakpoint_addr; 193 } 194 195