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