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)
2773101ba33SJim Ingham             {
278*cf2667c4SJim Ingham                 size_t num_matches = 0;
2793101ba33SJim Ingham                 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2803101ba33SJim Ingham                 if (log)
281*cf2667c4SJim Ingham                     num_matches = 1;
282*cf2667c4SJim Ingham                 bool return_value = avoid_regexp_to_use->Execute(frame_function_name, num_matches);
283*cf2667c4SJim Ingham                 if (return_value)
284*cf2667c4SJim Ingham                 {
285*cf2667c4SJim Ingham                     if (log)
286*cf2667c4SJim Ingham                     {
287*cf2667c4SJim Ingham                         std::string match;
288*cf2667c4SJim Ingham                         avoid_regexp_to_use->GetMatchAtIndex(frame_function_name,0, match);
289*cf2667c4SJim Ingham                         log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".",
2903101ba33SJim Ingham                                      frame_function_name,
291*cf2667c4SJim Ingham                                      avoid_regexp_to_use->GetText(),
292*cf2667c4SJim Ingham                                      match.c_str());
293*cf2667c4SJim Ingham                     }
2943101ba33SJim Ingham 
2953101ba33SJim Ingham                 }
2963101ba33SJim Ingham                 return return_value;
2973101ba33SJim Ingham             }
298a56c8006SJim Ingham         }
299a56c8006SJim Ingham     }
300a56c8006SJim Ingham     return false;
301a56c8006SJim Ingham }
302a56c8006SJim Ingham 
30330fdc8d8SChris Lattner ThreadPlan *
30430fdc8d8SChris Lattner ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
30530fdc8d8SChris Lattner {
306a56c8006SJim Ingham     bool should_step_out = false;
30730fdc8d8SChris Lattner     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
3083101ba33SJim Ingham     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
30930fdc8d8SChris Lattner 
31073b472d4SGreg Clayton     if (flags.Test(eAvoidNoDebug))
311a56c8006SJim Ingham     {
31230fdc8d8SChris Lattner         if (!frame->HasDebugInformation())
313af0f1759SJim Ingham         {
314af0f1759SJim Ingham             if (log)
315af0f1759SJim Ingham                 log->Printf ("Stepping out of frame with no debug info");
316af0f1759SJim Ingham 
317a56c8006SJim Ingham             should_step_out = true;
318a56c8006SJim Ingham         }
319af0f1759SJim Ingham     }
320a56c8006SJim Ingham 
321a56c8006SJim Ingham     if (current_plan->GetKind() == eKindStepInRange)
322a56c8006SJim Ingham     {
323a56c8006SJim Ingham         ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
324c627682eSJim Ingham         if (step_in_range_plan->m_step_into_target)
325c627682eSJim Ingham         {
326c627682eSJim Ingham             SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
327c627682eSJim Ingham             if (sc.symbol != NULL)
328c627682eSJim Ingham             {
329c627682eSJim Ingham                 // First try an exact match, since that's cheap with ConstStrings.  Then do a strstr compare.
330c627682eSJim Ingham                 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
331c627682eSJim Ingham                 {
332c627682eSJim Ingham                     should_step_out = false;
333c627682eSJim Ingham                 }
334c627682eSJim Ingham                 else
335c627682eSJim Ingham                 {
336c627682eSJim Ingham                     const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
337c627682eSJim Ingham                     const char *function_name = sc.GetFunctionName().AsCString();
338c627682eSJim Ingham 
339c627682eSJim Ingham                     if (function_name == NULL)
340c627682eSJim Ingham                         should_step_out = true;
341c627682eSJim Ingham                     else if (strstr (function_name, target_name) == NULL)
342c627682eSJim Ingham                         should_step_out = true;
343c627682eSJim Ingham                 }
3443101ba33SJim Ingham                 if (log && should_step_out)
3453101ba33SJim Ingham                     log->Printf("Stepping out of frame %s which did not match step into target %s.",
3463101ba33SJim Ingham                                 sc.GetFunctionName().AsCString(),
3473101ba33SJim Ingham                                 step_in_range_plan->m_step_into_target.AsCString());
348c627682eSJim Ingham             }
349c627682eSJim Ingham         }
350c627682eSJim Ingham 
351c627682eSJim Ingham         if (!should_step_out)
352c627682eSJim Ingham         {
353c627682eSJim Ingham             ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
3543101ba33SJim Ingham             // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidRegexp.
355a56c8006SJim Ingham             should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
356a56c8006SJim Ingham         }
357a56c8006SJim Ingham     }
358a56c8006SJim Ingham 
359c627682eSJim Ingham 
360a56c8006SJim Ingham     if (should_step_out)
36130fdc8d8SChris Lattner     {
36230fdc8d8SChris Lattner         // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
3634a58e968SJim Ingham         // We really should have all plans take the tri-state for "stop others" so we can do the right
3644a58e968SJim Ingham         // thing.  For now let's be safe and always run others when we are likely to run arbitrary code.
3654a58e968SJim Ingham         const bool stop_others = false;
366481cef25SGreg Clayton         return current_plan->GetThread().QueueThreadPlanForStepOut (false,
367481cef25SGreg Clayton                                                                     NULL,
368481cef25SGreg Clayton                                                                     true,
3694a58e968SJim Ingham                                                                     stop_others,
370481cef25SGreg Clayton                                                                     eVoteNo,
371481cef25SGreg Clayton                                                                     eVoteNoOpinion,
372481cef25SGreg Clayton                                                                     0); // Frame index
37330fdc8d8SChris Lattner     }
37430fdc8d8SChris Lattner 
37530fdc8d8SChris Lattner     return NULL;
37630fdc8d8SChris Lattner }
377fbbfe6ecSJim Ingham 
378fbbfe6ecSJim Ingham bool
3790161b49cSJim Ingham ThreadPlanStepInRange::PlanExplainsStop (Event *event_ptr)
380fbbfe6ecSJim Ingham {
381fbbfe6ecSJim Ingham     // We always explain a stop.  Either we've just done a single step, in which
382fbbfe6ecSJim Ingham     // case we'll do our ordinary processing, or we stopped for some
383fbbfe6ecSJim Ingham     // reason that isn't handled by our sub-plans, in which case we want to just stop right
384fbbfe6ecSJim Ingham     // away.
385c627682eSJim Ingham     // In general, we don't want to mark the plan as complete for unexplained stops.
386c627682eSJim Ingham     // For instance, if you step in to some code with no debug info, so you step out
387c627682eSJim Ingham     // and in the course of that hit a breakpoint, then you want to stop & show the user
388c627682eSJim Ingham     // the breakpoint, but not unship the step in plan, since you still may want to complete that
389c627682eSJim Ingham     // plan when you continue.  This is particularly true when doing "step in to target function."
390c627682eSJim Ingham     // stepping.
391fbbfe6ecSJim Ingham     //
392fbbfe6ecSJim Ingham     // The only variation is that if we are doing "step by running to next branch" in which case
393fbbfe6ecSJim Ingham     // if we hit our branch breakpoint we don't set the plan to complete.
394fbbfe6ecSJim Ingham 
395f02a2e96SJim Ingham     if (m_virtual_step)
396f02a2e96SJim Ingham         return true;
397f02a2e96SJim Ingham 
398fbbfe6ecSJim Ingham     StopInfoSP stop_info_sp = GetPrivateStopReason();
399fbbfe6ecSJim Ingham     if (stop_info_sp)
400fbbfe6ecSJim Ingham     {
401fbbfe6ecSJim Ingham         StopReason reason = stop_info_sp->GetStopReason();
402fbbfe6ecSJim Ingham 
403fbbfe6ecSJim Ingham         switch (reason)
404fbbfe6ecSJim Ingham         {
405fbbfe6ecSJim Ingham         case eStopReasonBreakpoint:
406fbbfe6ecSJim Ingham             if (NextRangeBreakpointExplainsStop(stop_info_sp))
407fbbfe6ecSJim Ingham                 return true;
408fbbfe6ecSJim Ingham         case eStopReasonWatchpoint:
409fbbfe6ecSJim Ingham         case eStopReasonSignal:
410fbbfe6ecSJim Ingham         case eStopReasonException:
41190ba8115SGreg Clayton         case eStopReasonExec:
412f85defaeSAndrew Kaylor         case eStopReasonThreadExiting:
413513c6bb8SJim Ingham             {
414513c6bb8SJim Ingham                 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
415fbbfe6ecSJim Ingham                 if (log)
416fbbfe6ecSJim Ingham                     log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
417513c6bb8SJim Ingham             }
418c627682eSJim Ingham             return false;
419fbbfe6ecSJim Ingham             break;
420fbbfe6ecSJim Ingham         default:
421fbbfe6ecSJim Ingham             break;
422fbbfe6ecSJim Ingham         }
423fbbfe6ecSJim Ingham     }
424fbbfe6ecSJim Ingham     return true;
425fbbfe6ecSJim Ingham }
426513c6bb8SJim Ingham 
427513c6bb8SJim Ingham bool
428513c6bb8SJim Ingham ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan)
429513c6bb8SJim Ingham {
430513c6bb8SJim Ingham     if (resume_state == eStateStepping && current_plan)
431513c6bb8SJim Ingham     {
432513c6bb8SJim Ingham         // See if we are about to step over a virtual inlined call.
433513c6bb8SJim Ingham         bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
434513c6bb8SJim Ingham         if (step_without_resume)
435513c6bb8SJim Ingham         {
436513c6bb8SJim Ingham             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
437513c6bb8SJim Ingham             if (log)
438513c6bb8SJim Ingham                 log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d",
439513c6bb8SJim Ingham                              m_thread.GetCurrentInlinedDepth());
440513c6bb8SJim Ingham             SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
441f02a2e96SJim Ingham 
442f02a2e96SJim Ingham             // FIXME: Maybe it would be better to create a InlineStep stop reason, but then
443f02a2e96SJim Ingham             // the whole rest of the world would have to handle that stop reason.
444f02a2e96SJim Ingham             m_virtual_step = true;
445513c6bb8SJim Ingham         }
446513c6bb8SJim Ingham         return !step_without_resume;
447513c6bb8SJim Ingham     }
448513c6bb8SJim Ingham     else
449513c6bb8SJim Ingham         return ThreadPlan::WillResume(resume_state, current_plan);
450513c6bb8SJim Ingham 
451513c6bb8SJim Ingham }
452