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