This checkin is the first step in making the lldb thread stepping mechanism more accessible from
the user level.  It adds the ability to invent new stepping modes implemented by python classes,
and to view the current thread plan stack and to some extent alter it.

I haven't gotten to documentation or tests yet.  But this should not cause any behavior changes
if you don't use it, so its safe to check it in now and work on it incrementally.

llvm-svn: 218642
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index f8ea250..30e0ffb 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -32,6 +32,7 @@
 #include "lldb/Target/ThreadPlan.h"
 #include "lldb/Target/ThreadPlanCallFunction.h"
 #include "lldb/Target/ThreadPlanBase.h"
+#include "lldb/Target/ThreadPlanPython.h"
 #include "lldb/Target/ThreadPlanStepInstruction.h"
 #include "lldb/Target/ThreadPlanStepOut.h"
 #include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
@@ -652,17 +653,18 @@
 
                 if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint)
                 {
-                    ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this);
-                    if (step_bp_plan)
+                    ThreadPlanSP step_bp_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
+                    if (step_bp_plan_sp)
                     {
-                        ThreadPlanSP step_bp_plan_sp;
-                        step_bp_plan->SetPrivate (true);
+                        ;
+                        step_bp_plan_sp->SetPrivate (true);
 
                         if (GetCurrentPlan()->RunState() != eStateStepping)
                         {
+                            ThreadPlanStepOverBreakpoint *step_bp_plan
+                                    = static_cast<ThreadPlanStepOverBreakpoint *>(step_bp_plan_sp.get());
                             step_bp_plan->SetAutoContinue(true);
                         }
-                        step_bp_plan_sp.reset (step_bp_plan);
                         QueueThreadPlan (step_bp_plan_sp, false);
                     }
                 }
@@ -1290,6 +1292,36 @@
         m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
 }
 
+bool
+Thread::DiscardUserThreadPlansUpToIndex (uint32_t thread_index)
+{
+    // Count the user thread plans from the back end to get the number of the one we want
+    // to discard:
+
+    uint32_t idx = 0;
+    ThreadPlan *up_to_plan_ptr = nullptr;
+
+    for (ThreadPlanSP plan_sp : m_plan_stack)
+    {
+        if (plan_sp->GetPrivate())
+            continue;
+        if (idx == thread_index)
+        {
+            up_to_plan_ptr = plan_sp.get();
+            break;
+        }
+        else
+            idx++;
+    }
+
+    if (up_to_plan_ptr == nullptr)
+        return false;
+
+    DiscardThreadPlansUpToPlan(up_to_plan_ptr);
+    return true;
+}
+    
+
 void
 Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
 {
@@ -1483,18 +1515,16 @@
     LazyBool step_out_avoids_code_without_debug_info
 )
 {
-    ThreadPlanSP thread_plan_sp;
-    ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this,
+    ThreadPlanSP thread_plan_sp (new ThreadPlanStepInRange (*this,
                                                              range,
                                                              addr_context,
                                                              stop_other_threads,
                                                              step_in_avoids_code_without_debug_info,
-                                                             step_out_avoids_code_without_debug_info);
+                                                             step_out_avoids_code_without_debug_info));
+    ThreadPlanStepInRange *plan = static_cast<ThreadPlanStepInRange *>(thread_plan_sp.get());
     
     if (step_in_target)
         plan->SetStepInTarget(step_in_target);
-    
-    thread_plan_sp.reset (plan);
 
     QueueThreadPlan (thread_plan_sp, abort_other_plans);
     return thread_plan_sp;
@@ -1546,17 +1576,18 @@
     uint32_t frame_idx
 )
 {
-    ThreadPlanStepOut *new_plan = new ThreadPlanStepOut (*this,
+    ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut (*this,
                                                         addr_context, 
                                                         first_insn, 
                                                         stop_other_threads, 
                                                         stop_vote, 
                                                         run_vote, 
                                                         frame_idx,
-                                                        eLazyBoolNo);
+                                                        eLazyBoolNo));
+
+    ThreadPlanStepOut *new_plan = static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
     new_plan->ClearShouldStopHereCallbacks();
-    ThreadPlanSP thread_plan_sp(new_plan);
-    
+
     if (thread_plan_sp->ValidatePlan(NULL))
     {
         QueueThreadPlan (thread_plan_sp, abort_other_plans);
@@ -1602,61 +1633,105 @@
 
 }
 
+lldb::ThreadPlanSP
+Thread::QueueThreadPlanForStepScripted (bool abort_other_plans,
+                                        const char *class_name,
+                                        bool stop_other_threads)
+{
+    ThreadPlanSP thread_plan_sp (new ThreadPlanPython (*this, class_name));
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    // This seems a little funny, but I don't want to have to split up the constructor and the
+    // DidPush in the scripted plan, that seems annoying.
+    // That means the constructor has to be in DidPush.
+    // So I have to validate the plan AFTER pushing it, and then take it off again...
+    if (!thread_plan_sp->ValidatePlan(nullptr))
+    {
+        DiscardThreadPlansUpToPlan(thread_plan_sp);
+        return ThreadPlanSP();
+    }
+    else
+        return thread_plan_sp;
+
+}
+
 uint32_t
 Thread::GetIndexID () const
 {
     return m_index_id;
 }
 
-void
-Thread::DumpThreadPlans (lldb_private::Stream *s) const
+static void
+PrintPlanElement (Stream *s, const ThreadPlanSP &plan, lldb::DescriptionLevel desc_level, int32_t elem_idx)
 {
-    uint32_t stack_size = m_plan_stack.size();
-    int i;
-    s->Indent();
-    s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4" PRIx64 ", stack_size = %d\n", GetIndexID(), GetID(), stack_size);
-    for (i = stack_size - 1; i >= 0; i--)
-    {
         s->IndentMore();
         s->Indent();
-        s->Printf ("Element %d: ", i);
-        m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
+        s->Printf ("Element %d: ", elem_idx);
+        plan->GetDescription (s, desc_level);
         s->EOL();
         s->IndentLess();
+}
+
+static void
+PrintPlanStack (Stream *s, const std::vector<lldb::ThreadPlanSP> &plan_stack, lldb::DescriptionLevel desc_level, bool include_internal)
+{
+    int32_t print_idx = 0;
+    for (ThreadPlanSP plan_sp : plan_stack)
+    {
+        if (include_internal || !plan_sp->GetPrivate())
+        {
+            PrintPlanElement (s, plan_sp, desc_level, print_idx++);
+        }
     }
+}
+
+void
+Thread::DumpThreadPlans (Stream *s,
+                         lldb::DescriptionLevel desc_level,
+                         bool include_internal,
+                         bool ignore_boring_threads) const
+{
+    uint32_t stack_size = m_plan_stack.size();
+
+    if (ignore_boring_threads)
+    {
+        uint32_t stack_size = m_plan_stack.size();
+        uint32_t completed_stack_size = m_completed_plan_stack.size();
+        uint32_t discarded_stack_size = m_discarded_plan_stack.size();
+        if (stack_size == 1 && completed_stack_size == 0 && discarded_stack_size == 0)
+        {
+            s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 "\n", GetIndexID(), GetID());
+            s->IndentMore();
+            s->Indent();
+            s->Printf("No active thread plans\n");
+            s->IndentLess();
+            return;
+        }
+    }
+
+    s->Indent();
+    s->Printf ("thread #%u: tid = 0x%4.4" PRIx64 ":\n", GetIndexID(), GetID());
+    s->IndentMore();
+    s->Indent();
+    s->Printf ("Active plan stack:\n");
+    PrintPlanStack (s, m_plan_stack, desc_level, include_internal);
 
     stack_size = m_completed_plan_stack.size();
     if (stack_size > 0)
     {
         s->Indent();
-        s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
-        for (i = stack_size - 1; i >= 0; i--)
-        {
-            s->IndentMore();
-            s->Indent();
-            s->Printf ("Element %d: ", i);
-            m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
-            s->EOL();
-            s->IndentLess();
-        }
+        s->Printf ("Completed Plan Stack:\n");
+        PrintPlanStack (s, m_completed_plan_stack, desc_level, include_internal);
     }
 
     stack_size = m_discarded_plan_stack.size();
     if (stack_size > 0)
     {
         s->Indent();
-        s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
-        for (i = stack_size - 1; i >= 0; i--)
-        {
-            s->IndentMore();
-            s->Indent();
-            s->Printf ("Element %d: ", i);
-            m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
-            s->EOL();
-            s->IndentLess();
-        }
+        s->Printf ("Discarded Plan Stack:\n");
+        PrintPlanStack (s, m_discarded_plan_stack, desc_level, include_internal);
     }
 
+    s->IndentLess();
 }
 
 TargetSP
diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp
new file mode 100644
index 0000000..e196d81
--- /dev/null
+++ b/lldb/source/Target/ThreadPlanPython.cpp
@@ -0,0 +1,192 @@
+//===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Target/ThreadPlan.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanPython.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanPython
+//----------------------------------------------------------------------
+
+ThreadPlanPython::ThreadPlanPython (Thread &thread, const char *class_name) :
+    ThreadPlan (ThreadPlan::eKindPython,
+                "Python based Thread Plan",
+                thread,
+                eVoteNoOpinion,
+                eVoteNoOpinion),
+    m_class_name (class_name)
+{
+    SetIsMasterPlan (true);
+    SetOkayToDiscard (true);
+    SetPrivate (false);
+}
+
+ThreadPlanPython::~ThreadPlanPython ()
+{
+    // FIXME, do I need to decrement the ref count on this implementation object to make it go away?
+}
+
+bool
+ThreadPlanPython::ValidatePlan (Stream *error)
+{
+    // I have to postpone setting up the implementation till after the constructor because I need to call
+    // shared_from_this, which you can't do in the constructor.  So I'll do it here.
+    if (m_implementation_sp)
+        return true;
+    else
+        return false;
+}
+
+void
+ThreadPlanPython::DidPush()
+{
+    // We set up the script side in DidPush, so that it can push other plans in the constructor,
+    // and doesn't have to care about the details of DidPush.
+
+    if (!m_class_name.empty())
+    {
+        ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+        if (script_interp)
+        {
+            m_implementation_sp = script_interp->CreateScriptedThreadPlan (m_class_name.c_str(), this->shared_from_this());
+        }
+    }
+}
+
+bool
+ThreadPlanPython::ShouldStop (Event *event_ptr)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf ("%s called on Python Thread Plan: %s )",
+                    __PRETTY_FUNCTION__, m_class_name.c_str());
+
+    bool should_stop = true;
+    if (m_implementation_sp)
+    {
+        ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+        if (script_interp)
+        {
+            bool script_error;
+            should_stop = script_interp->ScriptedThreadPlanShouldStop (m_implementation_sp, event_ptr, script_error);
+            if (script_error)
+                SetPlanComplete(false);
+        }
+    }
+    return should_stop;
+}
+
+bool
+ThreadPlanPython::DoPlanExplainsStop (Event *event_ptr)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf ("%s called on Python Thread Plan: %s )",
+                    __PRETTY_FUNCTION__, m_class_name.c_str());
+
+    bool explains_stop = true;
+    if (m_implementation_sp)
+    {
+        ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+        if (script_interp)
+        {
+            bool script_error;
+            explains_stop = script_interp->ScriptedThreadPlanExplainsStop (m_implementation_sp, event_ptr, script_error);
+            if (script_error)
+                SetPlanComplete(false);
+        }
+    }
+    return explains_stop;
+}
+
+bool
+ThreadPlanPython::MischiefManaged ()
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf ("%s called on Python Thread Plan: %s )",
+                    __PRETTY_FUNCTION__, m_class_name.c_str());
+    bool mischief_managed = true;
+    if (m_implementation_sp)
+    {
+        // I don't really need mischief_managed, since it's simpler to just call SetPlanComplete in should_stop.
+        mischief_managed = IsPlanComplete();
+        if (mischief_managed)
+            m_implementation_sp.reset();
+    }
+    return mischief_managed;
+}
+
+lldb::StateType
+ThreadPlanPython::GetPlanRunState ()
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf ("%s called on Python Thread Plan: %s )",
+                     __PRETTY_FUNCTION__,
+                     m_class_name.c_str());
+    lldb::StateType run_state = eStateRunning;
+    if (m_implementation_sp)
+    {
+        ScriptInterpreter *script_interp = m_thread.GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+        if (script_interp)
+        {
+            bool script_error;
+            run_state = script_interp->ScriptedThreadPlanGetRunState (m_implementation_sp, script_error);
+        }
+    }
+    return run_state;
+}
+
+// The ones below are not currently exported to Python.
+
+bool
+ThreadPlanPython::StopOthers ()
+{
+    // For now Python plans run all threads, but we should add some controls for this.
+    return false;
+}
+
+void
+ThreadPlanPython::GetDescription (Stream *s,
+                                lldb::DescriptionLevel level)
+{
+    s->Printf ("Python thread plan implemented by class %s.", m_class_name.c_str());
+}
+
+bool
+ThreadPlanPython::WillStop ()
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf ("%s called on Python Thread Plan: %s )",
+                    __PRETTY_FUNCTION__, m_class_name.c_str());
+    return true;
+}
diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp
index 3e9abef..1e7b045 100644
--- a/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -128,17 +128,31 @@
 ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
     if (level == lldb::eDescriptionLevelBrief)
-        s->Printf("step in");
-    else
     {
-        s->Printf ("Stepping through range (stepping into functions): ");
-        DumpRanges(s);
-        const char *step_into_target = m_step_into_target.AsCString();
-        if (step_into_target && step_into_target[0] != '\0')
-            s->Printf (" targeting %s.", m_step_into_target.AsCString());
-        else
-            s->PutChar('.');
+        s->Printf("step in");
+        return;
     }
+
+    s->Printf ("Stepping in");
+    bool printed_line_info = false;
+    if (m_addr_context.line_entry.IsValid())
+    {
+        s->Printf (" through line ");
+        m_addr_context.line_entry.DumpStopContext (s, false);
+        printed_line_info = true;
+    }
+
+    const char *step_into_target = m_step_into_target.AsCString();
+    if (step_into_target && step_into_target[0] != '\0')
+        s->Printf (" targeting %s", m_step_into_target.AsCString());
+
+    if (!printed_line_info || level == eDescriptionLevelVerbose)
+    {
+        s->Printf (" using ranges:");
+        DumpRanges(s);
+    }
+
+    s->PutChar('.');
 }
 
 bool
@@ -303,6 +317,7 @@
     else
     {
         m_no_more_plans = false;
+        m_sub_plan_sp->SetPrivate(true);
         return false;
     }
 }
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp
index b62f557..0ded99b 100644
--- a/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -54,7 +54,6 @@
     m_return_addr (LLDB_INVALID_ADDRESS),
     m_stop_others (stop_others),
     m_immediate_step_from_function(NULL)
-
 {
     SetFlagsToDefault();
     SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
@@ -90,6 +89,7 @@
                                                             frame_idx - 1,
                                                             eLazyBoolNo));
             static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
+            m_step_out_to_inline_plan_sp->SetPrivate(true);
         }
         else
         {
@@ -177,10 +177,34 @@
         else if (m_step_through_inline_plan_sp)
             s->Printf ("Stepping out by stepping through inlined function.");
         else
-            s->Printf ("Stepping out from address 0x%" PRIx64 " to return address 0x%" PRIx64 " using breakpoint site %d",
-                       (uint64_t)m_step_from_insn,
-                       (uint64_t)m_return_addr,
-                       m_return_bp_id);
+        {
+            s->Printf ("Stepping out from ");
+            Address tmp_address;
+            if (tmp_address.SetLoadAddress (m_step_from_insn, &GetTarget()))
+            {
+                tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
+            }
+            else
+            {
+                s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn);
+            }
+
+            // FIXME: find some useful way to present the m_return_id, since there may be multiple copies of the
+            // same function on the stack.
+
+            s->Printf ("returning to frame at ");
+            if (tmp_address.SetLoadAddress (m_return_addr, &GetTarget()))
+            {
+                tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
+            }
+            else
+            {
+                s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_return_addr);
+            }
+
+            if (level == eDescriptionLevelVerbose)
+                s->Printf(" using breakpoint site %d", m_return_bp_id);
+        }
     }
 }
 
@@ -474,11 +498,16 @@
                 inlined_sc.target_sp = GetTarget().shared_from_this();
                 RunMode run_mode = m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
                 const LazyBool avoid_no_debug = eLazyBoolNo;
-                ThreadPlanStepOverRange *step_through_inline_plan_ptr = new ThreadPlanStepOverRange(m_thread, 
-                                                                                                    inline_range, 
-                                                                                                    inlined_sc, 
-                                                                                                    run_mode,
-                                                                                                    avoid_no_debug);
+
+                m_step_through_inline_plan_sp.reset (new ThreadPlanStepOverRange(m_thread, 
+                                                                                 inline_range, 
+                                                                                 inlined_sc, 
+                                                                                 run_mode,
+                                                                                 avoid_no_debug));
+                ThreadPlanStepOverRange *step_through_inline_plan_ptr
+                        = static_cast<ThreadPlanStepOverRange *>(m_step_through_inline_plan_sp.get());
+                m_step_through_inline_plan_sp->SetPrivate(true);
+                        
                 step_through_inline_plan_ptr->SetOkayToDiscard(true);                                                                                    
                 StreamString errors;
                 if (!step_through_inline_plan_ptr->ValidatePlan(&errors))
@@ -493,7 +522,7 @@
                     if (inlined_block->GetRangeAtIndex (i, inline_range))
                         step_through_inline_plan_ptr->AddRange (inline_range);
                 }
-                m_step_through_inline_plan_sp.reset (step_through_inline_plan_ptr);
+
                 if (queue_now)
                     m_thread.QueueThreadPlan (m_step_through_inline_plan_sp, false);
                 return true;
diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp
index a4f3743..a6d65e4 100644
--- a/lldb/source/Target/ThreadPlanStepOverRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp
@@ -62,12 +62,26 @@
 ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
     if (level == lldb::eDescriptionLevelBrief)
-        s->Printf("step over");
-    else
     {
-        s->Printf ("stepping through range (stepping over functions): ");
-        DumpRanges(s);    
+        s->Printf("step over");
+        return;
     }
+    s->Printf ("Stepping over");
+    bool printed_line_info = false;
+    if (m_addr_context.line_entry.IsValid())
+    {
+        s->Printf (" line ");
+        m_addr_context.line_entry.DumpStopContext (s, false);
+        printed_line_info = true;
+    }
+
+    if (!printed_line_info || level == eDescriptionLevelVerbose)
+    {
+        s->Printf (" using ranges: ");
+        DumpRanges(s);
+    }
+
+    s->PutChar('.');
 }
 
 void
@@ -317,11 +331,15 @@
     {
         new_plan_sp = CheckShouldStopHereAndQueueStepOut (frame_order);
     }
-    
+
     if (!new_plan_sp)
         m_no_more_plans = true;
     else
+    {
+        // Any new plan will be an implementation plan, so mark it private:
+        new_plan_sp->SetPrivate(true);
         m_no_more_plans = false;
+    }
 
     if (!new_plan_sp)
     {
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index 82ca59f..adc515c 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -44,7 +44,8 @@
                                           Thread &thread, 
                                           const AddressRange &range, 
                                           const SymbolContext &addr_context, 
-                                          lldb::RunMode stop_others) :
+                                          lldb::RunMode stop_others,
+                                          bool given_ranges_only) :
     ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
     m_addr_context (addr_context),
     m_address_ranges (),
@@ -53,7 +54,8 @@
     m_parent_stack_id(),
     m_no_more_plans (false),
     m_first_run_event (true),
-    m_use_fast_step(false)
+    m_use_fast_step(false),
+    m_given_ranges_only (given_ranges_only)
 {
     m_use_fast_step = GetTarget().GetUseFastStepping();
     AddRange(range);
@@ -149,7 +151,7 @@
             break;
     }
     
-    if (!ret_value)
+    if (!ret_value && !m_given_ranges_only)
     {
         // See if we've just stepped to another part of the same line number...
         StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();