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 running other threads in general, since we're setting a breakpoint and 99 // continuing. So only stop others if we are explicitly told to do so. 100 101 bool stop_others; 102 if (m_stop_others == lldb::eOnlyThisThread) 103 stop_others = false; 104 else 105 stop_others = true; 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 // We really should have all plans take the tri-state for "stop others" so we can do the right 295 // thing. For now let's be safe and always run others when we are likely to run arbitrary code. 296 const bool stop_others = false; 297 return current_plan->GetThread().QueueThreadPlanForStepOut (false, 298 NULL, 299 true, 300 stop_others, 301 eVoteNo, 302 eVoteNoOpinion, 303 0); // Frame index 304 } 305 306 return NULL; 307 } 308 309 bool 310 ThreadPlanStepInRange::PlanExplainsStop () 311 { 312 // We always explain a stop. Either we've just done a single step, in which 313 // case we'll do our ordinary processing, or we stopped for some 314 // reason that isn't handled by our sub-plans, in which case we want to just stop right 315 // away. 316 // We also set ourselves complete when we stop for this sort of unintended reason, but mark 317 // success as false so we don't end up being the reason for the stop. 318 // 319 // The only variation is that if we are doing "step by running to next branch" in which case 320 // if we hit our branch breakpoint we don't set the plan to complete. 321 322 if (m_virtual_step) 323 return true; 324 325 StopInfoSP stop_info_sp = GetPrivateStopReason(); 326 if (stop_info_sp) 327 { 328 StopReason reason = stop_info_sp->GetStopReason(); 329 330 switch (reason) 331 { 332 case eStopReasonBreakpoint: 333 if (NextRangeBreakpointExplainsStop(stop_info_sp)) 334 return true; 335 case eStopReasonWatchpoint: 336 case eStopReasonSignal: 337 case eStopReasonException: 338 { 339 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 340 if (log) 341 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 342 SetPlanComplete(false); 343 } 344 break; 345 default: 346 break; 347 } 348 } 349 return true; 350 } 351 352 bool 353 ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan) 354 { 355 if (resume_state == eStateStepping && current_plan) 356 { 357 // See if we are about to step over a virtual inlined call. 358 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 359 if (step_without_resume) 360 { 361 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 362 if (log) 363 log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d", 364 m_thread.GetCurrentInlinedDepth()); 365 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 366 367 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 368 // the whole rest of the world would have to handle that stop reason. 369 m_virtual_step = true; 370 } 371 return !step_without_resume; 372 } 373 else 374 return ThreadPlan::WillResume(resume_state, current_plan); 375 376 } 377