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 if (IsPlanComplete()) 88 return eVoteYes; 89 else 90 return eVoteNo; 91 } 92 93 bool 94 ThreadPlanStepRange::InRange () 95 { 96 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 97 bool ret_value = false; 98 99 lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC(); 100 101 ret_value = m_address_range.ContainsLoadAddress(pc_load_addr, &m_thread.GetProcess()); 102 103 if (!ret_value) 104 { 105 // See if we've just stepped to another part of the same line number... 106 StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get(); 107 108 SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything)); 109 if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid()) 110 { 111 if ((m_addr_context.line_entry.file == new_context.line_entry.file) 112 && (m_addr_context.line_entry.line == new_context.line_entry.line)) 113 { 114 m_addr_context = new_context; 115 m_address_range = m_addr_context.line_entry.range; 116 ret_value = true; 117 if (log) 118 { 119 StreamString s; 120 m_address_range.Dump (&s, &m_thread.GetProcess(), Address::DumpStyleLoadAddress); 121 122 log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData()); 123 } 124 } 125 } 126 127 } 128 129 if (!ret_value && log) 130 log->Printf ("Step range plan out of range to 0x%llx", pc_load_addr); 131 132 return ret_value; 133 } 134 135 bool 136 ThreadPlanStepRange::InSymbol() 137 { 138 lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); 139 Process *process = m_thread.CalculateProcess(); 140 141 if (m_addr_context.function != NULL) 142 { 143 return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, process); 144 } 145 else if (m_addr_context.symbol != NULL) 146 { 147 return m_addr_context.symbol->GetAddressRangeRef().ContainsLoadAddress (cur_pc, process); 148 } 149 return false; 150 } 151 152 // FIXME: This should also handle inlining if we aren't going to do inlining in the 153 // main stack. 154 // 155 // Ideally we should remember the whole stack frame list, and then compare that 156 // to the current list. 157 158 bool 159 ThreadPlanStepRange::FrameIsYounger () 160 { 161 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 162 uint32_t current_depth = m_thread.GetStackFrameCount(); 163 if (current_depth == m_stack_depth) 164 { 165 if (log) 166 log->Printf ("Step range FrameIsYounger still in start function."); 167 return false; 168 } 169 else if (current_depth < m_stack_depth) 170 { 171 if (log) 172 log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 173 return false; 174 } 175 else 176 { 177 if (log) 178 log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 179 return true; 180 } 181 } 182 183 bool 184 ThreadPlanStepRange::FrameIsOlder () 185 { 186 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 187 uint32_t current_depth = m_thread.GetStackFrameCount(); 188 if (current_depth == m_stack_depth) 189 { 190 if (log) 191 log->Printf ("Step range FrameIsOlder still in start function."); 192 return false; 193 } 194 else if (current_depth < m_stack_depth) 195 { 196 if (log) 197 log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); 198 return true; 199 } 200 else 201 { 202 if (log) 203 log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); 204 return false; 205 } 206 } 207 208 bool 209 ThreadPlanStepRange::StopOthers () 210 { 211 if (m_stop_others == lldb::eOnlyThisThread 212 || m_stop_others == lldb::eOnlyDuringStepping) 213 return true; 214 else 215 return false; 216 } 217 218 bool 219 ThreadPlanStepRange::WillStop () 220 { 221 return true; 222 } 223 224 StateType 225 ThreadPlanStepRange::RunState () 226 { 227 return eStateStepping; 228 } 229 230 bool 231 ThreadPlanStepRange::MischiefManaged () 232 { 233 bool done = true; 234 if (!IsPlanComplete()) 235 { 236 if (InRange()) 237 { 238 done = false; 239 } 240 else if (!FrameIsOlder()) 241 { 242 if (m_no_more_plans) 243 done = true; 244 else 245 done = false; 246 } 247 else 248 done = true; 249 } 250 251 if (done) 252 { 253 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 254 if (log) 255 log->Printf("Completed step through range plan."); 256 ThreadPlan::MischiefManaged (); 257 return true; 258 } 259 else 260 { 261 return false; 262 } 263 264 } 265