1*30fdc8d8SChris Lattner //===-- ThreadPlanStepRange.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 10*30fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepRange.h" 11*30fdc8d8SChris Lattner 12*30fdc8d8SChris Lattner // C Includes 13*30fdc8d8SChris Lattner // C++ Includes 14*30fdc8d8SChris Lattner // Other libraries and framework includes 15*30fdc8d8SChris Lattner // Project includes 16*30fdc8d8SChris Lattner 17*30fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 18*30fdc8d8SChris Lattner #include "lldb/Core/Log.h" 19*30fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 20*30fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 21*30fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 22*30fdc8d8SChris Lattner #include "lldb/Target/Process.h" 23*30fdc8d8SChris Lattner #include "lldb/Symbol/Function.h" 24*30fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 25*30fdc8d8SChris Lattner 26*30fdc8d8SChris Lattner using namespace lldb; 27*30fdc8d8SChris Lattner using namespace lldb_private; 28*30fdc8d8SChris Lattner 29*30fdc8d8SChris Lattner 30*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 31*30fdc8d8SChris Lattner // ThreadPlanStepRange: Step through a stack range, either stepping over or into 32*30fdc8d8SChris Lattner // based on the value of \a type. 33*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 34*30fdc8d8SChris Lattner 35*30fdc8d8SChris Lattner ThreadPlanStepRange::ThreadPlanStepRange (const char *name, Thread &thread, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_others) : 36*30fdc8d8SChris Lattner ThreadPlan (name, thread, eVoteNoOpinion, eVoteNoOpinion), 37*30fdc8d8SChris Lattner m_address_range (range), 38*30fdc8d8SChris Lattner m_addr_context (addr_context), 39*30fdc8d8SChris Lattner m_stop_others (stop_others), 40*30fdc8d8SChris Lattner m_stack_depth (0), 41*30fdc8d8SChris Lattner m_no_more_plans (false), 42*30fdc8d8SChris Lattner m_stack_id (), 43*30fdc8d8SChris Lattner m_first_run_event (true) 44*30fdc8d8SChris Lattner { 45*30fdc8d8SChris Lattner m_stack_depth = m_thread.GetStackFrameCount(); 46*30fdc8d8SChris Lattner m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); 47*30fdc8d8SChris Lattner } 48*30fdc8d8SChris Lattner 49*30fdc8d8SChris Lattner ThreadPlanStepRange::~ThreadPlanStepRange () 50*30fdc8d8SChris Lattner { 51*30fdc8d8SChris Lattner } 52*30fdc8d8SChris Lattner 53*30fdc8d8SChris Lattner bool 54*30fdc8d8SChris Lattner ThreadPlanStepRange::ValidatePlan (Stream *error) 55*30fdc8d8SChris Lattner { 56*30fdc8d8SChris Lattner return true; 57*30fdc8d8SChris Lattner } 58*30fdc8d8SChris Lattner 59*30fdc8d8SChris Lattner bool 60*30fdc8d8SChris Lattner ThreadPlanStepRange::PlanExplainsStop () 61*30fdc8d8SChris Lattner { 62*30fdc8d8SChris Lattner // We don't explain signals or breakpoints (breakpoints that handle stepping in or 63*30fdc8d8SChris Lattner // out will be handled by a child plan. 64*30fdc8d8SChris Lattner Thread::StopInfo info; 65*30fdc8d8SChris Lattner if (m_thread.GetStopInfo (&info)) 66*30fdc8d8SChris Lattner { 67*30fdc8d8SChris Lattner StopReason reason = info.GetStopReason(); 68*30fdc8d8SChris Lattner 69*30fdc8d8SChris Lattner switch (reason) 70*30fdc8d8SChris Lattner { 71*30fdc8d8SChris Lattner case eStopReasonBreakpoint: 72*30fdc8d8SChris Lattner case eStopReasonWatchpoint: 73*30fdc8d8SChris Lattner case eStopReasonSignal: 74*30fdc8d8SChris Lattner case eStopReasonException: 75*30fdc8d8SChris Lattner return false; 76*30fdc8d8SChris Lattner default: 77*30fdc8d8SChris Lattner return true; 78*30fdc8d8SChris Lattner } 79*30fdc8d8SChris Lattner } 80*30fdc8d8SChris Lattner return true; 81*30fdc8d8SChris Lattner } 82*30fdc8d8SChris Lattner 83*30fdc8d8SChris Lattner Vote 84*30fdc8d8SChris Lattner ThreadPlanStepRange::ShouldReportStop (Event *event_ptr) 85*30fdc8d8SChris Lattner { 86*30fdc8d8SChris Lattner if (IsPlanComplete()) 87*30fdc8d8SChris Lattner return eVoteYes; 88*30fdc8d8SChris Lattner else 89*30fdc8d8SChris Lattner return eVoteNo; 90*30fdc8d8SChris Lattner } 91*30fdc8d8SChris Lattner 92*30fdc8d8SChris Lattner bool 93*30fdc8d8SChris Lattner ThreadPlanStepRange::InRange () 94*30fdc8d8SChris Lattner { 95*30fdc8d8SChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 96*30fdc8d8SChris Lattner bool ret_value = false; 97*30fdc8d8SChris Lattner 98*30fdc8d8SChris Lattner lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 99*30fdc8d8SChris Lattner 100*30fdc8d8SChris Lattner ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess()); 101*30fdc8d8SChris Lattner 102*30fdc8d8SChris Lattner if (!ret_value) 103*30fdc8d8SChris Lattner { 104*30fdc8d8SChris Lattner // See if we've just stepped to another part of the same line number... 105*30fdc8d8SChris Lattner StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 106*30fdc8d8SChris Lattner 107*30fdc8d8SChris Lattner SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 108*30fdc8d8SChris Lattner if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 109*30fdc8d8SChris Lattner { 110*30fdc8d8SChris Lattner if ((m_addr_context.line_entry.file == new_context.line_entry.file) 111*30fdc8d8SChris Lattner && (m_addr_context.line_entry.line == new_context.line_entry.line)) 112*30fdc8d8SChris Lattner { 113*30fdc8d8SChris Lattner m_addr_context = new_context; 114*30fdc8d8SChris Lattner m_address_range = m_addr_context.line_entry.range; 115*30fdc8d8SChris Lattner ret_value = true; 116*30fdc8d8SChris Lattner if (log) 117*30fdc8d8SChris Lattner { 118*30fdc8d8SChris Lattner StreamString s; 119*30fdc8d8SChris Lattner m_address_range.Dump (&s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress); 120*30fdc8d8SChris Lattner 121*30fdc8d8SChris Lattner log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 122*30fdc8d8SChris Lattner } 123*30fdc8d8SChris Lattner } 124*30fdc8d8SChris Lattner } 125*30fdc8d8SChris Lattner 126*30fdc8d8SChris Lattner } 127*30fdc8d8SChris Lattner 128*30fdc8d8SChris Lattner if (!ret_value && log) 129*30fdc8d8SChris Lattner log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr); 130*30fdc8d8SChris Lattner 131*30fdc8d8SChris Lattner return ret_value; 132*30fdc8d8SChris Lattner } 133*30fdc8d8SChris Lattner 134*30fdc8d8SChris Lattner bool 135*30fdc8d8SChris Lattner ThreadPlanStepRange::InSymbol() 136*30fdc8d8SChris Lattner { 137*30fdc8d8SChris Lattner lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 138*30fdc8d8SChris Lattner Process *process = m_thread.CalculateProcess(); 139*30fdc8d8SChris Lattner 140*30fdc8d8SChris Lattner if (m_addr_context.function != NULL) 141*30fdc8d8SChris Lattner { 142*30fdc8d8SChris Lattner return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, process); 143*30fdc8d8SChris Lattner } 144*30fdc8d8SChris Lattner else if (m_addr_context.symbol != NULL) 145*30fdc8d8SChris Lattner { 146*30fdc8d8SChris Lattner return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, process); 147*30fdc8d8SChris Lattner } 148*30fdc8d8SChris Lattner return false; 149*30fdc8d8SChris Lattner } 150*30fdc8d8SChris Lattner 151*30fdc8d8SChris Lattner // FIXME: This should also handle inlining if we aren't going to do inlining in the 152*30fdc8d8SChris Lattner // main stack. 153*30fdc8d8SChris Lattner // 154*30fdc8d8SChris Lattner // Ideally we should remember the whole stack frame list, and then compare that 155*30fdc8d8SChris Lattner // to the current list. 156*30fdc8d8SChris Lattner 157*30fdc8d8SChris Lattner bool 158*30fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsYounger () 159*30fdc8d8SChris Lattner { 160*30fdc8d8SChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 161*30fdc8d8SChris Lattner uint32_t current_depth = m_thread.GetStackFrameCount(); 162*30fdc8d8SChris Lattner if (current_depth == m_stack_depth) 163*30fdc8d8SChris Lattner { 164*30fdc8d8SChris Lattner if (log) 165*30fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger still in start function."); 166*30fdc8d8SChris Lattner return false; 167*30fdc8d8SChris Lattner } 168*30fdc8d8SChris Lattner else if (current_depth < m_stack_depth) 169*30fdc8d8SChris Lattner { 170*30fdc8d8SChris Lattner if (log) 171*30fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 172*30fdc8d8SChris Lattner return false; 173*30fdc8d8SChris Lattner } 174*30fdc8d8SChris Lattner else 175*30fdc8d8SChris Lattner { 176*30fdc8d8SChris Lattner if (log) 177*30fdc8d8SChris Lattner log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 178*30fdc8d8SChris Lattner return true; 179*30fdc8d8SChris Lattner } 180*30fdc8d8SChris Lattner } 181*30fdc8d8SChris Lattner 182*30fdc8d8SChris Lattner bool 183*30fdc8d8SChris Lattner ThreadPlanStepRange::FrameIsOlder () 184*30fdc8d8SChris Lattner { 185*30fdc8d8SChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 186*30fdc8d8SChris Lattner uint32_t current_depth = m_thread.GetStackFrameCount(); 187*30fdc8d8SChris Lattner if (current_depth == m_stack_depth) 188*30fdc8d8SChris Lattner { 189*30fdc8d8SChris Lattner if (log) 190*30fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder still in start function."); 191*30fdc8d8SChris Lattner return false; 192*30fdc8d8SChris Lattner } 193*30fdc8d8SChris Lattner else if (current_depth < m_stack_depth) 194*30fdc8d8SChris Lattner { 195*30fdc8d8SChris Lattner if (log) 196*30fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 197*30fdc8d8SChris Lattner return true; 198*30fdc8d8SChris Lattner } 199*30fdc8d8SChris Lattner else 200*30fdc8d8SChris Lattner { 201*30fdc8d8SChris Lattner if (log) 202*30fdc8d8SChris Lattner log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 203*30fdc8d8SChris Lattner return false; 204*30fdc8d8SChris Lattner } 205*30fdc8d8SChris Lattner } 206*30fdc8d8SChris Lattner 207*30fdc8d8SChris Lattner bool 208*30fdc8d8SChris Lattner ThreadPlanStepRange::StopOthers () 209*30fdc8d8SChris Lattner { 210*30fdc8d8SChris Lattner if (m_stop_others == lldb::eOnlyThisThread 211*30fdc8d8SChris Lattner || m_stop_others == lldb::eOnlyDuringStepping) 212*30fdc8d8SChris Lattner return true; 213*30fdc8d8SChris Lattner else 214*30fdc8d8SChris Lattner return false; 215*30fdc8d8SChris Lattner } 216*30fdc8d8SChris Lattner 217*30fdc8d8SChris Lattner bool 218*30fdc8d8SChris Lattner ThreadPlanStepRange::WillStop () 219*30fdc8d8SChris Lattner { 220*30fdc8d8SChris Lattner return true; 221*30fdc8d8SChris Lattner } 222*30fdc8d8SChris Lattner 223*30fdc8d8SChris Lattner StateType 224*30fdc8d8SChris Lattner ThreadPlanStepRange::RunState () 225*30fdc8d8SChris Lattner { 226*30fdc8d8SChris Lattner return eStateStepping; 227*30fdc8d8SChris Lattner } 228*30fdc8d8SChris Lattner 229*30fdc8d8SChris Lattner bool 230*30fdc8d8SChris Lattner ThreadPlanStepRange::MischiefManaged () 231*30fdc8d8SChris Lattner { 232*30fdc8d8SChris Lattner bool done = true; 233*30fdc8d8SChris Lattner if (!IsPlanComplete()) 234*30fdc8d8SChris Lattner { 235*30fdc8d8SChris Lattner if (InRange()) 236*30fdc8d8SChris Lattner { 237*30fdc8d8SChris Lattner done = false; 238*30fdc8d8SChris Lattner } 239*30fdc8d8SChris Lattner else if (!FrameIsOlder()) 240*30fdc8d8SChris Lattner { 241*30fdc8d8SChris Lattner if (m_no_more_plans) 242*30fdc8d8SChris Lattner done = true; 243*30fdc8d8SChris Lattner else 244*30fdc8d8SChris Lattner done = false; 245*30fdc8d8SChris Lattner } 246*30fdc8d8SChris Lattner else 247*30fdc8d8SChris Lattner done = true; 248*30fdc8d8SChris Lattner } 249*30fdc8d8SChris Lattner 250*30fdc8d8SChris Lattner if (done) 251*30fdc8d8SChris Lattner { 252*30fdc8d8SChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 253*30fdc8d8SChris Lattner if (log) 254*30fdc8d8SChris Lattner log->Printf("Completed step through range plan."); 255*30fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 256*30fdc8d8SChris Lattner return true; 257*30fdc8d8SChris Lattner } 258*30fdc8d8SChris Lattner else 259*30fdc8d8SChris Lattner { 260*30fdc8d8SChris Lattner return false; 261*30fdc8d8SChris Lattner } 262*30fdc8d8SChris Lattner 263*30fdc8d8SChris Lattner } 264