130fdc8d8SChris Lattner //===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInRange.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner 1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Log.h" 1930fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 20a56c8006SJim Ingham #include "lldb/Symbol/Symbol.h" 217ce490c6SJim Ingham #include "lldb/Symbol/Function.h" 2230fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2330fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 24514487e8SGreg Clayton #include "lldb/Target/Target.h" 2530fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2630fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h" 2730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h" 28a56c8006SJim Ingham #include "lldb/Core/RegularExpression.h" 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner using namespace lldb; 3130fdc8d8SChris Lattner using namespace lldb_private; 3230fdc8d8SChris Lattner 3330fdc8d8SChris Lattner uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug; 3430fdc8d8SChris Lattner 3530fdc8d8SChris Lattner //---------------------------------------------------------------------- 3630fdc8d8SChris Lattner // ThreadPlanStepInRange: Step through a stack range, either stepping over or into 3730fdc8d8SChris Lattner // based on the value of \a type. 3830fdc8d8SChris Lattner //---------------------------------------------------------------------- 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner ThreadPlanStepInRange::ThreadPlanStepInRange 4130fdc8d8SChris Lattner ( 4230fdc8d8SChris Lattner Thread &thread, 4330fdc8d8SChris Lattner const AddressRange &range, 4430fdc8d8SChris Lattner const SymbolContext &addr_context, 4530fdc8d8SChris Lattner lldb::RunMode stop_others 4630fdc8d8SChris Lattner ) : 47b01e742aSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 487ce490c6SJim Ingham ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 49f02a2e96SJim Ingham m_step_past_prologue (true), 50f02a2e96SJim Ingham m_virtual_step (false) 5130fdc8d8SChris Lattner { 5230fdc8d8SChris Lattner SetFlagsToDefault (); 5330fdc8d8SChris Lattner } 5430fdc8d8SChris Lattner 55c627682eSJim Ingham ThreadPlanStepInRange::ThreadPlanStepInRange 56c627682eSJim Ingham ( 57c627682eSJim Ingham Thread &thread, 58c627682eSJim Ingham const AddressRange &range, 59c627682eSJim Ingham const SymbolContext &addr_context, 60c627682eSJim Ingham const char *step_into_target, 61c627682eSJim Ingham lldb::RunMode stop_others 62c627682eSJim Ingham ) : 63c627682eSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 64c627682eSJim Ingham ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 65c627682eSJim Ingham m_step_past_prologue (true), 66c627682eSJim Ingham m_virtual_step (false), 67c627682eSJim Ingham m_step_into_target (step_into_target) 68c627682eSJim Ingham { 69c627682eSJim Ingham SetFlagsToDefault (); 70c627682eSJim Ingham } 71c627682eSJim Ingham 7230fdc8d8SChris Lattner ThreadPlanStepInRange::~ThreadPlanStepInRange () 7330fdc8d8SChris Lattner { 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner 7630fdc8d8SChris Lattner void 7730fdc8d8SChris Lattner ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) 7830fdc8d8SChris Lattner { 7930fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 8030fdc8d8SChris Lattner s->Printf("step in"); 8130fdc8d8SChris Lattner else 8230fdc8d8SChris Lattner { 8330fdc8d8SChris Lattner s->Printf ("Stepping through range (stepping into functions): "); 84c4c9fedcSJim Ingham DumpRanges(s); 85c627682eSJim Ingham s->Printf ("targeting %s.", m_step_into_target.AsCString()); 8630fdc8d8SChris Lattner } 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 8930fdc8d8SChris Lattner bool 9030fdc8d8SChris Lattner ThreadPlanStepInRange::ShouldStop (Event *event_ptr) 9130fdc8d8SChris Lattner { 922d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 9330fdc8d8SChris Lattner m_no_more_plans = false; 9430fdc8d8SChris Lattner 9530fdc8d8SChris Lattner if (log) 9630fdc8d8SChris Lattner { 9730fdc8d8SChris Lattner StreamString s; 98514487e8SGreg Clayton s.Address (m_thread.GetRegisterContext()->GetPC(), 991ac04c30SGreg Clayton m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 10030fdc8d8SChris Lattner log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); 10130fdc8d8SChris Lattner } 10230fdc8d8SChris Lattner 10325f66700SJim Ingham if (IsPlanComplete()) 10425f66700SJim Ingham return true; 10525f66700SJim Ingham 10630fdc8d8SChris Lattner ThreadPlan* new_plan = NULL; 10730fdc8d8SChris Lattner 108f02a2e96SJim Ingham if (m_virtual_step) 109f02a2e96SJim Ingham { 110f02a2e96SJim Ingham // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise 111f02a2e96SJim Ingham // we're done. 112f02a2e96SJim Ingham new_plan = InvokeShouldStopHereCallback(); 113f02a2e96SJim Ingham } 114f02a2e96SJim Ingham else 115f02a2e96SJim Ingham { 1164a58e968SJim Ingham // Stepping through should be done running other threads in general, since we're setting a breakpoint and 1174a58e968SJim Ingham // continuing. So only stop others if we are explicitly told to do so. 1189d790c5dSJim Ingham 11930fdc8d8SChris Lattner bool stop_others; 1204a58e968SJim Ingham if (m_stop_others == lldb::eOnlyThisThread) 12130fdc8d8SChris Lattner stop_others = false; 1224a58e968SJim Ingham else 1234a58e968SJim Ingham stop_others = true; 12430fdc8d8SChris Lattner 125b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 126b5c0d1ccSJim Ingham 127b5c0d1ccSJim Ingham if (frame_order == eFrameCompareOlder) 1285822173bSJim Ingham { 1295822173bSJim Ingham // If we're in an older frame then we should stop. 1305822173bSJim Ingham // 1315822173bSJim Ingham // A caveat to this is if we think the frame is older but we're actually in a trampoline. 1325822173bSJim Ingham // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are 1335822173bSJim Ingham // in a trampoline we think the frame is older because the trampoline confused the backtracer. 13418de2fdcSJim Ingham new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 1355822173bSJim Ingham if (new_plan == NULL) 1365822173bSJim Ingham return true; 1375822173bSJim Ingham else if (log) 1385822173bSJim Ingham { 1395822173bSJim Ingham log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); 1405822173bSJim Ingham } 1415822173bSJim Ingham 1425822173bSJim Ingham } 143564d8bc2SJim Ingham else if (frame_order == eFrameCompareEqual && InSymbol()) 1445822173bSJim Ingham { 1455822173bSJim Ingham // If we are not in a place we should step through, we're done. 1465822173bSJim Ingham // One tricky bit here is that some stubs don't push a frame, so we have to check 1475822173bSJim Ingham // both the case of a frame that is younger, or the same as this frame. 1485822173bSJim Ingham // However, if the frame is the same, and we are still in the symbol we started 1495822173bSJim Ingham // in, the we don't need to do this. This first check isn't strictly necessary, 1505822173bSJim Ingham // but it is more efficient. 1515822173bSJim Ingham 152564d8bc2SJim Ingham // If we're still in the range, keep going, either by running to the next branch breakpoint, or by 153564d8bc2SJim Ingham // stepping. 154564d8bc2SJim Ingham if (InRange()) 155564d8bc2SJim Ingham { 156564d8bc2SJim Ingham SetNextBranchBreakpoint(); 157564d8bc2SJim Ingham return false; 158564d8bc2SJim Ingham } 159564d8bc2SJim Ingham 1605822173bSJim Ingham SetPlanComplete(); 161c627682eSJim Ingham m_no_more_plans = true; 1625822173bSJim Ingham return true; 1635822173bSJim Ingham } 1645822173bSJim Ingham 165564d8bc2SJim Ingham // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: 166564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 167564d8bc2SJim Ingham 1685822173bSJim Ingham // We may have set the plan up above in the FrameIsOlder section: 1695822173bSJim Ingham 1705822173bSJim Ingham if (new_plan == NULL) 17118de2fdcSJim Ingham new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 17208b87e0dSJim Ingham 17308b87e0dSJim Ingham if (log) 17408b87e0dSJim Ingham { 17508b87e0dSJim Ingham if (new_plan != NULL) 17608b87e0dSJim Ingham log->Printf ("Found a step through plan: %s", new_plan->GetName()); 17708b87e0dSJim Ingham else 17808b87e0dSJim Ingham log->Printf ("No step through plan found."); 17908b87e0dSJim Ingham } 18008b87e0dSJim Ingham 18130fdc8d8SChris Lattner // If not, give the "should_stop" callback a chance to push a plan to get us out of here. 18230fdc8d8SChris Lattner // But only do that if we actually have stepped in. 183b5c0d1ccSJim Ingham if (!new_plan && frame_order == eFrameCompareYounger) 18430fdc8d8SChris Lattner new_plan = InvokeShouldStopHereCallback(); 18530fdc8d8SChris Lattner 1867ce490c6SJim Ingham // If we've stepped in and we are going to stop here, check to see if we were asked to 1877ce490c6SJim Ingham // run past the prologue, and if so do that. 1887ce490c6SJim Ingham 189b5c0d1ccSJim Ingham if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue) 1907ce490c6SJim Ingham { 1917ce490c6SJim Ingham lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); 1927ce490c6SJim Ingham if (curr_frame) 1937ce490c6SJim Ingham { 1947ce490c6SJim Ingham size_t bytes_to_skip = 0; 1957ce490c6SJim Ingham lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); 1967ce490c6SJim Ingham Address func_start_address; 1977ce490c6SJim Ingham 1987ce490c6SJim Ingham SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); 1997ce490c6SJim Ingham 2007ce490c6SJim Ingham if (sc.function) 2017ce490c6SJim Ingham { 2027ce490c6SJim Ingham func_start_address = sc.function->GetAddressRange().GetBaseAddress(); 203d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 2047ce490c6SJim Ingham bytes_to_skip = sc.function->GetPrologueByteSize(); 2057ce490c6SJim Ingham } 2067ce490c6SJim Ingham else if (sc.symbol) 2077ce490c6SJim Ingham { 208e7612134SGreg Clayton func_start_address = sc.symbol->GetAddress(); 209d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 2107ce490c6SJim Ingham bytes_to_skip = sc.symbol->GetPrologueByteSize(); 2117ce490c6SJim Ingham } 2127ce490c6SJim Ingham 2137ce490c6SJim Ingham if (bytes_to_skip != 0) 2147ce490c6SJim Ingham { 2157ce490c6SJim Ingham func_start_address.Slide (bytes_to_skip); 21620ad3c40SCaroline Tice log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 2177ce490c6SJim Ingham if (log) 2187ce490c6SJim Ingham log->Printf ("Pushing past prologue "); 2197ce490c6SJim Ingham 2207ce490c6SJim Ingham new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); 2217ce490c6SJim Ingham } 2227ce490c6SJim Ingham } 2237ce490c6SJim Ingham } 224f02a2e96SJim Ingham } 2257ce490c6SJim Ingham 22630fdc8d8SChris Lattner if (new_plan == NULL) 22730fdc8d8SChris Lattner { 22830fdc8d8SChris Lattner m_no_more_plans = true; 22930fdc8d8SChris Lattner SetPlanComplete(); 23030fdc8d8SChris Lattner return true; 23130fdc8d8SChris Lattner } 23230fdc8d8SChris Lattner else 23330fdc8d8SChris Lattner { 23430fdc8d8SChris Lattner m_no_more_plans = false; 23530fdc8d8SChris Lattner return false; 23630fdc8d8SChris Lattner } 23730fdc8d8SChris Lattner } 23830fdc8d8SChris Lattner 23930fdc8d8SChris Lattner void 24030fdc8d8SChris Lattner ThreadPlanStepInRange::SetFlagsToDefault () 24130fdc8d8SChris Lattner { 24230fdc8d8SChris Lattner GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner 24530fdc8d8SChris Lattner void 246a56c8006SJim Ingham ThreadPlanStepInRange::SetAvoidRegexp(const char *name) 247a56c8006SJim Ingham { 248a56c8006SJim Ingham if (m_avoid_regexp_ap.get() == NULL) 249a56c8006SJim Ingham m_avoid_regexp_ap.reset (new RegularExpression(name)); 250a56c8006SJim Ingham 251a56c8006SJim Ingham m_avoid_regexp_ap->Compile (name); 252a56c8006SJim Ingham } 253a56c8006SJim Ingham 254a56c8006SJim Ingham void 25530fdc8d8SChris Lattner ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) 25630fdc8d8SChris Lattner { 25730fdc8d8SChris Lattner // TODO: Should we test this for sanity? 25830fdc8d8SChris Lattner ThreadPlanStepInRange::s_default_flag_values = new_value; 25930fdc8d8SChris Lattner } 26030fdc8d8SChris Lattner 261a56c8006SJim Ingham bool 262a56c8006SJim Ingham ThreadPlanStepInRange::FrameMatchesAvoidRegexp () 263a56c8006SJim Ingham { 264a56c8006SJim Ingham StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); 265a56c8006SJim Ingham 26667cc0636SGreg Clayton const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 267ee8aea10SJim Ingham if (avoid_regexp_to_use == NULL) 268ee8aea10SJim Ingham avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 269ee8aea10SJim Ingham 270ee8aea10SJim Ingham if (avoid_regexp_to_use != NULL) 271a56c8006SJim Ingham { 2724592cbc4SGreg Clayton SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 273a56c8006SJim Ingham if (sc.symbol != NULL) 274a56c8006SJim Ingham { 2754592cbc4SGreg Clayton const char *frame_function_name = sc.GetFunctionName().GetCString(); 2764592cbc4SGreg Clayton if (frame_function_name) 2774592cbc4SGreg Clayton return avoid_regexp_to_use->Execute(frame_function_name); 278a56c8006SJim Ingham } 279a56c8006SJim Ingham } 280a56c8006SJim Ingham return false; 281a56c8006SJim Ingham } 282a56c8006SJim Ingham 28330fdc8d8SChris Lattner ThreadPlan * 28430fdc8d8SChris Lattner ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton) 28530fdc8d8SChris Lattner { 286a56c8006SJim Ingham bool should_step_out = false; 28730fdc8d8SChris Lattner StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 28830fdc8d8SChris Lattner 28973b472d4SGreg Clayton if (flags.Test(eAvoidNoDebug)) 290a56c8006SJim Ingham { 29130fdc8d8SChris Lattner if (!frame->HasDebugInformation()) 292af0f1759SJim Ingham { 293513c6bb8SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 294af0f1759SJim Ingham if (log) 295af0f1759SJim Ingham log->Printf ("Stepping out of frame with no debug info"); 296af0f1759SJim Ingham 297a56c8006SJim Ingham should_step_out = true; 298a56c8006SJim Ingham } 299af0f1759SJim Ingham } 300a56c8006SJim Ingham 301a56c8006SJim Ingham if (current_plan->GetKind() == eKindStepInRange) 302a56c8006SJim Ingham { 303a56c8006SJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 304c627682eSJim Ingham if (step_in_range_plan->m_step_into_target) 305c627682eSJim Ingham { 306c627682eSJim Ingham SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 307c627682eSJim Ingham if (sc.symbol != NULL) 308c627682eSJim Ingham { 309c627682eSJim Ingham // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. 310c627682eSJim Ingham if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) 311c627682eSJim Ingham { 312c627682eSJim Ingham should_step_out = false; 313c627682eSJim Ingham } 314c627682eSJim Ingham else 315c627682eSJim Ingham { 316c627682eSJim Ingham const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); 317c627682eSJim Ingham const char *function_name = sc.GetFunctionName().AsCString(); 318c627682eSJim Ingham 319c627682eSJim Ingham if (function_name == NULL) 320c627682eSJim Ingham should_step_out = true; 321c627682eSJim Ingham else if (strstr (function_name, target_name) == NULL) 322c627682eSJim Ingham should_step_out = true; 323c627682eSJim Ingham } 324c627682eSJim Ingham } 325c627682eSJim Ingham } 326c627682eSJim Ingham 327c627682eSJim Ingham if (!should_step_out) 328c627682eSJim Ingham { 329c627682eSJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 330a56c8006SJim Ingham should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp (); 331a56c8006SJim Ingham } 332a56c8006SJim Ingham } 333a56c8006SJim Ingham 334c627682eSJim Ingham 335a56c8006SJim Ingham if (should_step_out) 33630fdc8d8SChris Lattner { 33730fdc8d8SChris Lattner // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions. 3384a58e968SJim Ingham // We really should have all plans take the tri-state for "stop others" so we can do the right 3394a58e968SJim Ingham // thing. For now let's be safe and always run others when we are likely to run arbitrary code. 3404a58e968SJim Ingham const bool stop_others = false; 341481cef25SGreg Clayton return current_plan->GetThread().QueueThreadPlanForStepOut (false, 342481cef25SGreg Clayton NULL, 343481cef25SGreg Clayton true, 3444a58e968SJim Ingham stop_others, 345481cef25SGreg Clayton eVoteNo, 346481cef25SGreg Clayton eVoteNoOpinion, 347481cef25SGreg Clayton 0); // Frame index 34830fdc8d8SChris Lattner } 34930fdc8d8SChris Lattner 35030fdc8d8SChris Lattner return NULL; 35130fdc8d8SChris Lattner } 352fbbfe6ecSJim Ingham 353fbbfe6ecSJim Ingham bool 354fbbfe6ecSJim Ingham ThreadPlanStepInRange::PlanExplainsStop () 355fbbfe6ecSJim Ingham { 356fbbfe6ecSJim Ingham // We always explain a stop. Either we've just done a single step, in which 357fbbfe6ecSJim Ingham // case we'll do our ordinary processing, or we stopped for some 358fbbfe6ecSJim Ingham // reason that isn't handled by our sub-plans, in which case we want to just stop right 359fbbfe6ecSJim Ingham // away. 360c627682eSJim Ingham // In general, we don't want to mark the plan as complete for unexplained stops. 361c627682eSJim Ingham // For instance, if you step in to some code with no debug info, so you step out 362c627682eSJim Ingham // and in the course of that hit a breakpoint, then you want to stop & show the user 363c627682eSJim Ingham // the breakpoint, but not unship the step in plan, since you still may want to complete that 364c627682eSJim Ingham // plan when you continue. This is particularly true when doing "step in to target function." 365c627682eSJim Ingham // stepping. 366fbbfe6ecSJim Ingham // 367fbbfe6ecSJim Ingham // The only variation is that if we are doing "step by running to next branch" in which case 368fbbfe6ecSJim Ingham // if we hit our branch breakpoint we don't set the plan to complete. 369fbbfe6ecSJim Ingham 370f02a2e96SJim Ingham if (m_virtual_step) 371f02a2e96SJim Ingham return true; 372f02a2e96SJim Ingham 373fbbfe6ecSJim Ingham StopInfoSP stop_info_sp = GetPrivateStopReason(); 374fbbfe6ecSJim Ingham if (stop_info_sp) 375fbbfe6ecSJim Ingham { 376fbbfe6ecSJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 377fbbfe6ecSJim Ingham 378fbbfe6ecSJim Ingham switch (reason) 379fbbfe6ecSJim Ingham { 380fbbfe6ecSJim Ingham case eStopReasonBreakpoint: 381fbbfe6ecSJim Ingham if (NextRangeBreakpointExplainsStop(stop_info_sp)) 382fbbfe6ecSJim Ingham return true; 383fbbfe6ecSJim Ingham case eStopReasonWatchpoint: 384fbbfe6ecSJim Ingham case eStopReasonSignal: 385fbbfe6ecSJim Ingham case eStopReasonException: 38690ba8115SGreg Clayton case eStopReasonExec: 387*f85defaeSAndrew Kaylor case eStopReasonThreadExiting: 388513c6bb8SJim Ingham { 389513c6bb8SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 390fbbfe6ecSJim Ingham if (log) 391fbbfe6ecSJim Ingham log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 392513c6bb8SJim Ingham } 393c627682eSJim Ingham return false; 394fbbfe6ecSJim Ingham break; 395fbbfe6ecSJim Ingham default: 396fbbfe6ecSJim Ingham break; 397fbbfe6ecSJim Ingham } 398fbbfe6ecSJim Ingham } 399fbbfe6ecSJim Ingham return true; 400fbbfe6ecSJim Ingham } 401513c6bb8SJim Ingham 402513c6bb8SJim Ingham bool 403513c6bb8SJim Ingham ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan) 404513c6bb8SJim Ingham { 405513c6bb8SJim Ingham if (resume_state == eStateStepping && current_plan) 406513c6bb8SJim Ingham { 407513c6bb8SJim Ingham // See if we are about to step over a virtual inlined call. 408513c6bb8SJim Ingham bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 409513c6bb8SJim Ingham if (step_without_resume) 410513c6bb8SJim Ingham { 411513c6bb8SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 412513c6bb8SJim Ingham if (log) 413513c6bb8SJim Ingham log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d", 414513c6bb8SJim Ingham m_thread.GetCurrentInlinedDepth()); 415513c6bb8SJim Ingham SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 416f02a2e96SJim Ingham 417f02a2e96SJim Ingham // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 418f02a2e96SJim Ingham // the whole rest of the world would have to handle that stop reason. 419f02a2e96SJim Ingham m_virtual_step = true; 420513c6bb8SJim Ingham } 421513c6bb8SJim Ingham return !step_without_resume; 422513c6bb8SJim Ingham } 423513c6bb8SJim Ingham else 424513c6bb8SJim Ingham return ThreadPlan::WillResume(resume_state, current_plan); 425513c6bb8SJim Ingham 426513c6bb8SJim Ingham } 427