1 //===-- ThreadPlanStepInRange.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/ThreadPlanStepInRange.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/Symbol.h" 21 #include "lldb/Symbol/Function.h" 22 #include "lldb/Target/Process.h" 23 #include "lldb/Target/RegisterContext.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/Thread.h" 26 #include "lldb/Target/ThreadPlanStepOut.h" 27 #include "lldb/Target/ThreadPlanStepThrough.h" 28 #include "lldb/Core/RegularExpression.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug; 34 35 //---------------------------------------------------------------------- 36 // ThreadPlanStepInRange: Step through a stack range, either stepping over or into 37 // based on the value of \a type. 38 //---------------------------------------------------------------------- 39 40 ThreadPlanStepInRange::ThreadPlanStepInRange 41 ( 42 Thread &thread, 43 const AddressRange &range, 44 const SymbolContext &addr_context, 45 lldb::RunMode stop_others 46 ) : 47 ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 48 ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 49 m_step_past_prologue (true), 50 m_virtual_step (false) 51 { 52 SetFlagsToDefault (); 53 } 54 55 ThreadPlanStepInRange::~ThreadPlanStepInRange () 56 { 57 } 58 59 void 60 ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) 61 { 62 if (level == lldb::eDescriptionLevelBrief) 63 s->Printf("step in"); 64 else 65 { 66 s->Printf ("Stepping through range (stepping into functions): "); 67 DumpRanges(s); 68 } 69 } 70 71 bool 72 ThreadPlanStepInRange::ShouldStop (Event *event_ptr) 73 { 74 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 75 m_no_more_plans = false; 76 77 if (log) 78 { 79 StreamString s; 80 s.Address (m_thread.GetRegisterContext()->GetPC(), 81 m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 82 log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); 83 } 84 85 if (IsPlanComplete()) 86 return true; 87 88 ThreadPlan* new_plan = NULL; 89 90 if (m_virtual_step) 91 { 92 // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise 93 // we're done. 94 new_plan = InvokeShouldStopHereCallback(); 95 } 96 else 97 { 98 // Stepping through should be done stopping other threads in general, since we're setting a breakpoint and 99 // continuing... 100 101 bool stop_others; 102 if (m_stop_others != lldb::eAllThreads) 103 stop_others = true; 104 else 105 stop_others = false; 106 107 FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 108 109 if (frame_order == eFrameCompareOlder) 110 { 111 // If we're in an older frame then we should stop. 112 // 113 // A caveat to this is if we think the frame is older but we're actually in a trampoline. 114 // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are 115 // in a trampoline we think the frame is older because the trampoline confused the backtracer. 116 new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 117 if (new_plan == NULL) 118 return true; 119 else if (log) 120 { 121 log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); 122 } 123 124 } 125 else if (frame_order == eFrameCompareEqual && InSymbol()) 126 { 127 // If we are not in a place we should step through, we're done. 128 // One tricky bit here is that some stubs don't push a frame, so we have to check 129 // both the case of a frame that is younger, or the same as this frame. 130 // However, if the frame is the same, and we are still in the symbol we started 131 // in, the we don't need to do this. This first check isn't strictly necessary, 132 // but it is more efficient. 133 134 // If we're still in the range, keep going, either by running to the next branch breakpoint, or by 135 // stepping. 136 if (InRange()) 137 { 138 SetNextBranchBreakpoint(); 139 return false; 140 } 141 142 SetPlanComplete(); 143 return true; 144 } 145 146 // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: 147 ClearNextBranchBreakpoint(); 148 149 // We may have set the plan up above in the FrameIsOlder section: 150 151 if (new_plan == NULL) 152 new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 153 154 if (log) 155 { 156 if (new_plan != NULL) 157 log->Printf ("Found a step through plan: %s", new_plan->GetName()); 158 else 159 log->Printf ("No step through plan found."); 160 } 161 162 // If not, give the "should_stop" callback a chance to push a plan to get us out of here. 163 // But only do that if we actually have stepped in. 164 if (!new_plan && frame_order == eFrameCompareYounger) 165 new_plan = InvokeShouldStopHereCallback(); 166 167 // If we've stepped in and we are going to stop here, check to see if we were asked to 168 // run past the prologue, and if so do that. 169 170 if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue) 171 { 172 lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); 173 if (curr_frame) 174 { 175 size_t bytes_to_skip = 0; 176 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); 177 Address func_start_address; 178 179 SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); 180 181 if (sc.function) 182 { 183 func_start_address = sc.function->GetAddressRange().GetBaseAddress(); 184 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 185 bytes_to_skip = sc.function->GetPrologueByteSize(); 186 } 187 else if (sc.symbol) 188 { 189 func_start_address = sc.symbol->GetAddress(); 190 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 191 bytes_to_skip = sc.symbol->GetPrologueByteSize(); 192 } 193 194 if (bytes_to_skip != 0) 195 { 196 func_start_address.Slide (bytes_to_skip); 197 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 198 if (log) 199 log->Printf ("Pushing past prologue "); 200 201 new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); 202 } 203 } 204 } 205 } 206 207 if (new_plan == NULL) 208 { 209 m_no_more_plans = true; 210 SetPlanComplete(); 211 return true; 212 } 213 else 214 { 215 m_no_more_plans = false; 216 return false; 217 } 218 } 219 220 void 221 ThreadPlanStepInRange::SetFlagsToDefault () 222 { 223 GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); 224 } 225 226 void 227 ThreadPlanStepInRange::SetAvoidRegexp(const char *name) 228 { 229 if (m_avoid_regexp_ap.get() == NULL) 230 m_avoid_regexp_ap.reset (new RegularExpression(name)); 231 232 m_avoid_regexp_ap->Compile (name); 233 } 234 235 void 236 ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) 237 { 238 // TODO: Should we test this for sanity? 239 ThreadPlanStepInRange::s_default_flag_values = new_value; 240 } 241 242 bool 243 ThreadPlanStepInRange::FrameMatchesAvoidRegexp () 244 { 245 StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); 246 247 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 248 if (avoid_regexp_to_use == NULL) 249 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 250 251 if (avoid_regexp_to_use != NULL) 252 { 253 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 254 if (sc.symbol != NULL) 255 { 256 const char *frame_function_name = sc.GetFunctionName().GetCString(); 257 if (frame_function_name) 258 return avoid_regexp_to_use->Execute(frame_function_name); 259 } 260 } 261 return false; 262 } 263 264 ThreadPlan * 265 ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton) 266 { 267 bool should_step_out = false; 268 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 269 270 if (flags.Test(eAvoidNoDebug)) 271 { 272 if (!frame->HasDebugInformation()) 273 { 274 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 275 if (log) 276 log->Printf ("Stepping out of frame with no debug info"); 277 278 should_step_out = true; 279 } 280 } 281 282 if (!should_step_out) 283 { 284 if (current_plan->GetKind() == eKindStepInRange) 285 { 286 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 287 should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp (); 288 } 289 } 290 291 if (should_step_out) 292 { 293 // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions. 294 return current_plan->GetThread().QueueThreadPlanForStepOut (false, 295 NULL, 296 true, 297 current_plan->StopOthers(), 298 eVoteNo, 299 eVoteNoOpinion, 300 0); // Frame index 301 } 302 303 return NULL; 304 } 305 306 bool 307 ThreadPlanStepInRange::PlanExplainsStop () 308 { 309 // We always explain a stop. Either we've just done a single step, in which 310 // case we'll do our ordinary processing, or we stopped for some 311 // reason that isn't handled by our sub-plans, in which case we want to just stop right 312 // away. 313 // We also set ourselves complete when we stop for this sort of unintended reason, but mark 314 // success as false so we don't end up being the reason for the stop. 315 // 316 // The only variation is that if we are doing "step by running to next branch" in which case 317 // if we hit our branch breakpoint we don't set the plan to complete. 318 319 if (m_virtual_step) 320 return true; 321 322 StopInfoSP stop_info_sp = GetPrivateStopReason(); 323 if (stop_info_sp) 324 { 325 StopReason reason = stop_info_sp->GetStopReason(); 326 327 switch (reason) 328 { 329 case eStopReasonBreakpoint: 330 if (NextRangeBreakpointExplainsStop(stop_info_sp)) 331 return true; 332 case eStopReasonWatchpoint: 333 case eStopReasonSignal: 334 case eStopReasonException: 335 { 336 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 337 if (log) 338 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 339 SetPlanComplete(false); 340 } 341 break; 342 default: 343 break; 344 } 345 } 346 return true; 347 } 348 349 bool 350 ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan) 351 { 352 if (resume_state == eStateStepping && current_plan) 353 { 354 // See if we are about to step over a virtual inlined call. 355 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 356 if (step_without_resume) 357 { 358 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 359 if (log) 360 log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d", 361 m_thread.GetCurrentInlinedDepth()); 362 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 363 364 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 365 // the whole rest of the world would have to handle that stop reason. 366 m_virtual_step = true; 367 } 368 return !step_without_resume; 369 } 370 else 371 return ThreadPlan::WillResume(resume_state, current_plan); 372 373 } 374