[Lldb-commits] [lldb] r218642 - This checkin is the first step in making the lldb thread stepping mechanism more accessible from

Jim Ingham jingham at apple.com
Mon Sep 29 16:17:19 PDT 2014


Author: jingham
Date: Mon Sep 29 18:17:18 2014
New Revision: 218642

URL: http://llvm.org/viewvc/llvm-project?rev=218642&view=rev
Log:
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.

Added:
    lldb/trunk/include/lldb/API/SBThreadPlan.h
    lldb/trunk/include/lldb/Target/ThreadPlanPython.h
    lldb/trunk/scripts/Python/interface/SBThreadPlan.i
    lldb/trunk/source/API/SBThreadPlan.cpp
    lldb/trunk/source/Target/ThreadPlanPython.cpp
Modified:
    lldb/trunk/include/lldb/API/SBAddress.h
    lldb/trunk/include/lldb/API/SBDefines.h
    lldb/trunk/include/lldb/API/SBEvent.h
    lldb/trunk/include/lldb/API/SBStream.h
    lldb/trunk/include/lldb/API/SBThread.h
    lldb/trunk/include/lldb/Expression/ClangFunction.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/include/lldb/Target/ThreadPlan.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h
    lldb/trunk/include/lldb/lldb-private-enumerations.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/scripts/Python/build-swig-Python.sh
    lldb/trunk/scripts/Python/interface/SBThread.i
    lldb/trunk/scripts/Python/python-swigsafecast.swig
    lldb/trunk/scripts/Python/python-wrapper.swig
    lldb/trunk/scripts/lldb.swig
    lldb/trunk/source/API/SBCommandInterpreter.cpp
    lldb/trunk/source/API/SBEvent.cpp
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
    lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
    lldb/trunk/source/Target/ThreadPlanStepOut.cpp
    lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
    lldb/trunk/source/Target/ThreadPlanStepRange.cpp

Modified: lldb/trunk/include/lldb/API/SBAddress.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBAddress.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBAddress.h (original)
+++ lldb/trunk/include/lldb/API/SBAddress.h Mon Sep 29 18:17:18 2014
@@ -117,6 +117,7 @@ protected:
     friend class SBSymbolContext;
     friend class SBTarget;
     friend class SBThread;
+    friend class SBThreadPlan;
     friend class SBValue;
     friend class SBQueueItem;
 

Modified: lldb/trunk/include/lldb/API/SBDefines.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBDefines.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBDefines.h (original)
+++ lldb/trunk/include/lldb/API/SBDefines.h Mon Sep 29 18:17:18 2014
@@ -71,6 +71,7 @@ class LLDB_API SBSymbolContextList;
 class LLDB_API SBTarget;
 class LLDB_API SBThread;
 class LLDB_API SBThreadCollection;
+class LLDB_API SBThreadPlan;
 class LLDB_API SBType;
 class LLDB_API SBTypeCategory;
 class LLDB_API SBTypeEnumMember;

Modified: lldb/trunk/include/lldb/API/SBEvent.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBEvent.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBEvent.h (original)
+++ lldb/trunk/include/lldb/API/SBEvent.h Mon Sep 29 18:17:18 2014
@@ -30,6 +30,10 @@ public:
     // Make an event that contains a C string.
     SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len);
 
+    SBEvent (lldb::EventSP &event_sp);
+
+    SBEvent (lldb_private::Event *event_sp);
+
     ~SBEvent();
 
     const SBEvent &
@@ -77,8 +81,6 @@ protected:
     friend class SBThread;
     friend class SBWatchpoint;
 
-    SBEvent (lldb::EventSP &event_sp);
-
     lldb::EventSP &
     GetSP () const;
 

Modified: lldb/trunk/include/lldb/API/SBStream.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBStream.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBStream.h (original)
+++ lldb/trunk/include/lldb/API/SBStream.h Mon Sep 29 18:17:18 2014
@@ -85,6 +85,7 @@ protected:
     friend class SBSymbolContextList;
     friend class SBTarget;
     friend class SBThread;
+    friend class SBThreadPlan;
     friend class SBType;
     friend class SBTypeEnumMember;
     friend class SBTypeMemberFunction;

Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Mon Sep 29 18:17:18 2014
@@ -127,6 +127,9 @@ public:
                    uint32_t line);
 
     SBError
+    StepUsingScriptedThreadPlan (const char *script_class_name);
+
+    SBError
     JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line);
 
     void
@@ -216,6 +219,15 @@ public:
     bool
     SafeToCallFunctions ();
 
+#ifndef SWIG
+    lldb_private::Thread *
+    operator->();
+
+    lldb_private::Thread *
+    get();
+
+#endif
+
 protected:
     friend class SBBreakpoint;
     friend class SBBreakpointLocation;

Added: lldb/trunk/include/lldb/API/SBThreadPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThreadPlan.h?rev=218642&view=auto
==============================================================================
--- lldb/trunk/include/lldb/API/SBThreadPlan.h (added)
+++ lldb/trunk/include/lldb/API/SBThreadPlan.h Mon Sep 29 18:17:18 2014
@@ -0,0 +1,129 @@
+//===-- SBThread.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBThreadPlan_h_
+#define LLDB_SBThreadPlan_h_
+
+#include "lldb/API/SBDefines.h"
+
+#include <stdio.h>
+
+namespace lldb {
+
+class SBThreadPlan
+{
+
+friend class lldb_private::ThreadPlan;
+
+public:
+    SBThreadPlan ();
+
+    SBThreadPlan (const lldb::SBThreadPlan &threadPlan);
+    
+    SBThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp);
+
+    SBThreadPlan (lldb::SBThread &thread, const char *class_name);
+
+   ~SBThreadPlan ();
+
+    bool
+    IsValid() const;
+
+    void
+    Clear ();
+
+    lldb::StopReason
+    GetStopReason();
+
+    /// Get the number of words associated with the stop reason.
+    /// See also GetStopReasonDataAtIndex().
+    size_t
+    GetStopReasonDataCount();
+
+    //--------------------------------------------------------------------------
+    /// Get information associated with a stop reason.
+    ///
+    /// Breakpoint stop reasons will have data that consists of pairs of 
+    /// breakpoint IDs followed by the breakpoint location IDs (they always come
+    /// in pairs).
+    ///
+    /// Stop Reason              Count Data Type
+    /// ======================== ===== =========================================
+    /// eStopReasonNone          0
+    /// eStopReasonTrace         0
+    /// eStopReasonBreakpoint    N     duple: {breakpoint id, location id}
+    /// eStopReasonWatchpoint    1     watchpoint id
+    /// eStopReasonSignal        1     unix signal number
+    /// eStopReasonException     N     exception data
+    /// eStopReasonExec          0
+    /// eStopReasonPlanComplete  0
+    //--------------------------------------------------------------------------
+    uint64_t
+    GetStopReasonDataAtIndex(uint32_t idx);
+
+    SBThread
+    GetThread () const;
+
+    const lldb::SBThreadPlan &
+    operator = (const lldb::SBThreadPlan &rhs);
+
+    bool
+    GetDescription (lldb::SBStream &description) const;
+
+    void
+    SetPlanComplete (bool success);
+
+    bool
+    IsPlanComplete();
+
+    bool
+    IsValid();
+
+    // This section allows an SBThreadPlan to push another of the common types of plans...
+    SBThreadPlan
+    QueueThreadPlanForStepOverRange (SBAddress &start_address,
+                                     lldb::addr_t range_size);
+
+    SBThreadPlan
+    QueueThreadPlanForStepInRange (SBAddress &start_address,
+                                   lldb::addr_t range_size);
+
+    SBThreadPlan
+    QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn = false);
+
+    SBThreadPlan
+    QueueThreadPlanForRunToAddress (SBAddress address);
+
+#ifndef SWIG
+    lldb_private::ThreadPlan *
+    get();
+#endif
+
+protected:
+    friend class SBBreakpoint;
+    friend class SBBreakpointLocation;
+    friend class SBFrame;
+    friend class SBProcess;
+    friend class SBDebugger;
+    friend class SBValue;
+    friend class lldb_private::QueueImpl;
+    friend class SBQueueItem;
+
+#ifndef SWIG
+    void
+    SetThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp);
+#endif
+
+private:
+    lldb::ThreadPlanSP m_opaque_sp;
+};
+
+} // namespace lldb
+
+#endif  // LLDB_SBThreadPlan_h_

Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Mon Sep 29 18:17:18 2014
@@ -285,9 +285,9 @@ public:
     ///     True if the thread plan may simply be discarded if an error occurs.
     ///
     /// @return
-    ///     A ThreadPlan for executing the function.
+    ///     A ThreadPlan shared pointer for executing the function.
     //------------------------------------------------------------------
-    ThreadPlan *
+    lldb::ThreadPlanSP
     GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, 
                                  lldb::addr_t args_addr,
                                  const EvaluateExpressionOptions &options,

Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Mon Sep 29 18:17:18 2014
@@ -104,6 +104,12 @@ public:
                                                         const char *session_dictionary_name,
                                                         const lldb::ValueObjectSP& valobj_sp);
 
+    typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name,
+                                                        const char *session_dictionary_name,
+                                                        const lldb::ThreadPlanSP& thread_plan_sp);
+
+    typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error);
+
     typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name,
                                                const char *session_dictionary_name,
                                                const lldb::ProcessSP& process_sp);
@@ -348,6 +354,39 @@ public:
     }
     
     virtual lldb::ScriptInterpreterObjectSP
+    CreateScriptedThreadPlan (const char *class_name,
+                              lldb::ThreadPlanSP thread_plan_sp)
+    {
+        return lldb::ScriptInterpreterObjectSP();
+    }
+
+    virtual bool
+    ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                    Event *event,
+                                    bool &script_error)
+    {
+        script_error = true;
+        return true;
+    }
+
+    virtual bool
+    ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                  Event *event,
+                                  bool &script_error)
+    {
+        script_error = true;
+        return true;
+    }
+
+    virtual lldb::StateType
+    ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                   bool &script_error)
+    {
+        script_error = true;
+        return lldb::eStateStepping;
+    }
+
+    virtual lldb::ScriptInterpreterObjectSP
     LoadPluginModule (const FileSpec& file_spec,
                      lldb_private::Error& error)
     {
@@ -573,7 +612,9 @@ public:
                            SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
                            SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
                            SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
-                           SWIGPython_GetDynamicSetting swig_plugin_get);
+                           SWIGPython_GetDynamicSetting swig_plugin_get,
+                           SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+                           SWIGPythonCallThreadPlan swig_call_thread_plan);
 
     virtual void
     ResetOutputFileHandle (FILE *new_fh) { } //By default, do nothing.

Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Mon Sep 29 18:17:18 2014
@@ -80,6 +80,22 @@ public:
     lldb::ScriptInterpreterObjectSP
     CreateSyntheticScriptedProvider (const char *class_name,
                                      lldb::ValueObjectSP valobj);
+
+    lldb::ScriptInterpreterObjectSP
+    virtual CreateScriptedThreadPlan (const char *class_name,
+                                      lldb::ThreadPlanSP thread_plan);
+
+    virtual bool
+    ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                    Event *event,
+                                    bool &script_error);
+    virtual bool
+    ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                  Event *event,
+                                  bool &script_error);
+    virtual lldb::StateType
+    ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                   bool &script_error);
     
     virtual lldb::ScriptInterpreterObjectSP
     OSPlugin_CreatePluginObject (const char *class_name,
@@ -275,7 +291,9 @@ public:
                            SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
                            SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
                            SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
-                           SWIGPython_GetDynamicSetting swig_plugin_get);
+                           SWIGPython_GetDynamicSetting swig_plugin_get,
+                           SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+                           SWIGPythonCallThreadPlan swig_call_thread_plan);
 
     const char *
     GetDictionaryName ()

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Mon Sep 29 18:17:18 2014
@@ -912,6 +912,11 @@ public:
                                  bool stop_others,
                                  uint32_t frame_idx);
 
+    virtual lldb::ThreadPlanSP
+    QueueThreadPlanForStepScripted (bool abort_other_plans,
+                                    const char *class_name,
+                                    bool stop_other_threads);
+
     //------------------------------------------------------------------
     // Thread Plan accessors:
     //------------------------------------------------------------------
@@ -1041,6 +1046,20 @@ public:
 
     void
     DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr);
+
+    //------------------------------------------------------------------
+    /// Discards the plans queued on the plan stack of the current thread up to and
+    /// including the plan in that matches \a thread_index counting only
+    /// the non-Private plans.
+    ///
+    /// @param[in] up_to_plan_sp
+    ///   Discard all plans up to and including this user plan given by this index.
+    ///
+    /// @return
+    ///    \b true if there was a thread plan with that user index, \b false otherwise.
+    //------------------------------------------------------------------
+    bool
+    DiscardUserThreadPlansUpToIndex (uint32_t thread_index);
     
     //------------------------------------------------------------------
     /// Prints the current plan stack.
@@ -1050,7 +1069,10 @@ public:
     ///
     //------------------------------------------------------------------
     void
-    DumpThreadPlans (Stream *s) const;
+    DumpThreadPlans (Stream *s,
+                     lldb::DescriptionLevel desc_level = lldb::eDescriptionLevelVerbose,
+                     bool include_internal = true,
+                     bool ignore_boring = false) const;
     
     virtual bool
     CheckpointThreadState (ThreadStateCheckpoint &saved_state);

Modified: lldb/trunk/include/lldb/Target/ThreadPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlan.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlan.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlan.h Mon Sep 29 18:17:18 2014
@@ -223,6 +223,7 @@ namespace lldb_private {
 //------------------------------------------------------------------
 
 class ThreadPlan :
+    public std::enable_shared_from_this<ThreadPlan>,
     public UserID
 {
 public:
@@ -241,6 +242,7 @@ public:
         eKindNull,
         eKindBase,
         eKindCallFunction,
+        eKindPython,
         eKindStepInstruction,
         eKindStepOut,
         eKindStepOverBreakpoint,
@@ -687,7 +689,8 @@ protected:
     
     virtual lldb::StateType
     GetPlanRunState ();
-    
+
+    DISALLOW_COPY_AND_ASSIGN(ThreadPlanNull);
 };
 
 

Added: lldb/trunk/include/lldb/Target/ThreadPlanPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanPython.h?rev=218642&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanPython.h (added)
+++ lldb/trunk/include/lldb/Target/ThreadPlanPython.h Mon Sep 29 18:17:18 2014
@@ -0,0 +1,80 @@
+//===-- ThreadPlanPython.h --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ThreadPlan_Python_h_
+#define liblldb_ThreadPlan_Python_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanTracer.h"
+#include "lldb/Target/StopInfo.h"
+
+namespace lldb_private {
+
+//------------------------------------------------------------------
+//  ThreadPlanPython:
+//
+//------------------------------------------------------------------
+
+class ThreadPlanPython : public ThreadPlan
+{
+public:
+    ThreadPlanPython (Thread &thread, const char *class_name);
+    virtual ~ThreadPlanPython ();
+    
+    virtual void
+    GetDescription (Stream *s,
+                    lldb::DescriptionLevel level);
+
+    virtual bool
+    ValidatePlan (Stream *error);
+
+    virtual bool
+    ShouldStop (Event *event_ptr);
+
+    virtual bool
+    MischiefManaged ();
+
+    virtual bool
+    WillStop ();
+
+    virtual bool
+    StopOthers ();
+
+    virtual void
+    DidPush ();
+
+protected:
+    virtual bool
+    DoPlanExplainsStop (Event *event_ptr);
+    
+    virtual lldb::StateType
+    GetPlanRunState ();
+
+private:
+    std::string                     m_class_name;
+    lldb::ScriptInterpreterObjectSP m_implementation_sp;
+
+    DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython);
+};
+
+
+} // namespace lldb_private
+
+#endif  // liblldb_ThreadPlan_Python_h_

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h Mon Sep 29 18:17:18 2014
@@ -30,7 +30,8 @@ public:
                          Thread &thread,
                          const AddressRange &range,
                          const SymbolContext &addr_context,
-                         lldb::RunMode stop_others);
+                         lldb::RunMode stop_others,
+                         bool given_ranges_only = false);
 
     virtual ~ThreadPlanStepRange ();
 
@@ -83,6 +84,7 @@ protected:
     bool                      m_first_run_event; // We want to broadcast only one running event, our first.
     lldb::BreakpointSP        m_next_branch_bp_sp;
     bool                      m_use_fast_step;
+    bool                      m_given_ranges_only;
 
 private:
     std::vector<lldb::DisassemblerSP> m_instruction_ranges;

Modified: lldb/trunk/include/lldb/lldb-private-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-enumerations.h?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-private-enumerations.h Mon Sep 29 18:17:18 2014
@@ -22,7 +22,8 @@ typedef enum StepType
     eStepTypeTraceOver, ///< Single step one instruction, stepping over.
     eStepTypeInto,      ///< Single step into a specified context.
     eStepTypeOver,      ///< Single step over a specified context.
-    eStepTypeOut        ///< Single step out a specified context.
+    eStepTypeOut,       ///< Single step out a specified context.
+    eStepTypeScripted   ///< A step type implemented by the script interpreter.
 } StepType;
 
 //----------------------------------------------------------------------

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Sep 29 18:17:18 2014
@@ -613,6 +613,10 @@
 		49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */; };
 		49DCF702170E70120092F75E /* Materializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF700170E70120092F75E /* Materializer.cpp */; };
 		4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; };
+		4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */; };
+		4C56543319D1EFB6002E9C44 /* ThreadPlanPython.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */; };
+		4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543419D2297A002E9C44 /* SBThreadPlan.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */; };
 		4C6649A014EEE7F100B0316F /* StreamCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C66499F14EEE7F100B0316F /* StreamCallback.h */; };
 		4C6649A314EEE81000B0316F /* StreamCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6649A214EEE81000B0316F /* StreamCallback.cpp */; };
 		4C73152219B7D71700F865A4 /* Iterable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C73152119B7D71700F865A4 /* Iterable.h */; };
@@ -1893,6 +1897,11 @@
 		4C43DF8611069BFD00E55CBF /* ThreadPlanStepOverRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepOverRange.h; path = include/lldb/Target/ThreadPlanStepOverRange.h; sourceTree = "<group>"; };
 		4C43DF8911069C3200E55CBF /* ThreadPlanStepInRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepInRange.cpp; path = source/Target/ThreadPlanStepInRange.cpp; sourceTree = "<group>"; };
 		4C43DF8A11069C3200E55CBF /* ThreadPlanStepOverRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepOverRange.cpp; path = source/Target/ThreadPlanStepOverRange.cpp; sourceTree = "<group>"; };
+		4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanPython.cpp; path = source/Target/ThreadPlanPython.cpp; sourceTree = "<group>"; };
+		4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanPython.h; path = include/lldb/Target/ThreadPlanPython.h; sourceTree = "<group>"; };
+		4C56543419D2297A002E9C44 /* SBThreadPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBThreadPlan.h; path = include/lldb/API/SBThreadPlan.h; sourceTree = "<group>"; };
+		4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBThreadPlan.cpp; path = source/API/SBThreadPlan.cpp; sourceTree = "<group>"; };
+		4C56543819D22FD9002E9C44 /* SBThreadPlan.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBThreadPlan.i; sourceTree = "<group>"; };
 		4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectCommands.cpp; path = source/Commands/CommandObjectCommands.cpp; sourceTree = "<group>"; };
 		4C5DBBC711E3FEC60035160F /* CommandObjectCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectCommands.h; path = source/Commands/CommandObjectCommands.h; sourceTree = "<group>"; };
 		4C626533130F1B0A00C889F6 /* StreamTee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamTee.h; path = include/lldb/Core/StreamTee.h; sourceTree = "<group>"; };
@@ -2669,6 +2678,7 @@
 				2611FF0E142D83060017FEA3 /* SBSymbolContextList.i */,
 				2611FF0F142D83060017FEA3 /* SBTarget.i */,
 				2611FF10142D83060017FEA3 /* SBThread.i */,
+				4C56543819D22FD9002E9C44 /* SBThreadPlan.i */,
 				8CCB018419BA54930009FD44 /* SBThreadCollection.i */,
 				2611FF11142D83060017FEA3 /* SBType.i */,
 				9475C18A14E5EA1C001BFC6D /* SBTypeCategory.i */,
@@ -2786,6 +2796,8 @@
 				9A9831091125FC5800A56CB0 /* SBThread.cpp */,
 				8CCB018119BA4E210009FD44 /* SBThreadCollection.h */,
 				8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */,
+				4C56543419D2297A002E9C44 /* SBThreadPlan.h */,
+				4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */,
 				2617447911685869005ADD65 /* SBType.h */,
 				261744771168585B005ADD65 /* SBType.cpp */,
 				9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */,
@@ -3805,6 +3817,8 @@
 				49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */,
 				4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */,
 				4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */,
+				4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */,
+				4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */,
 				4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */,
 				4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */,
 				260C848010F50F0A00BB2B04 /* ThreadPlanStepInstruction.h */,
@@ -4403,6 +4417,7 @@
 				268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */,
 				2668022C115FD13D008E1FE4 /* SBTarget.h in Headers */,
 				2668022E115FD13D008E1FE4 /* SBThread.h in Headers */,
+				4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */,
 				263C493A178B50CF0070F12D /* SBModuleSpec.h in Headers */,
 				2617447A11685869005ADD65 /* SBType.h in Headers */,
 				9475C18914E5EA08001BFC6D /* SBTypeCategory.h in Headers */,
@@ -4495,6 +4510,7 @@
 				26DAED6015D327A200E15819 /* OptionValuePathMappings.h in Headers */,
 				26ACEC2815E077AE00E94760 /* Property.h in Headers */,
 				26491E3B15E1DB8600CBFFC2 /* OptionValueRegex.h in Headers */,
+				4C56543319D1EFB6002E9C44 /* ThreadPlanPython.h in Headers */,
 				2697A39515E404BA003E682C /* OptionValueArch.h in Headers */,
 				26474CBF18D0CB2D0073DEBA /* RegisterContextMach_i386.h in Headers */,
 				26474CC118D0CB2D0073DEBA /* RegisterContextMach_x86_64.h in Headers */,
@@ -4899,6 +4915,7 @@
 				9443B122140C18C40013457C /* SBData.cpp in Sources */,
 				4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */,
 				23059A101958B319007B8189 /* SBUnixSignals.cpp in Sources */,
+				4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */,
 				8CCB018319BA51BF0009FD44 /* SBThreadCollection.cpp in Sources */,
 				26B82840142D020F002DBC64 /* SBSection.cpp in Sources */,
 				B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */,
@@ -5176,6 +5193,7 @@
 				268900E613353E6F00698AC0 /* Variable.cpp in Sources */,
 				268900E713353E6F00698AC0 /* VariableList.cpp in Sources */,
 				268900E813353E6F00698AC0 /* ABI.cpp in Sources */,
+				4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */,
 				26AB92121819D74600E63F3E /* DWARFDataExtractor.cpp in Sources */,
 				268900E913353E6F00698AC0 /* CPPLanguageRuntime.cpp in Sources */,
 				268900EA13353E6F00698AC0 /* DynamicLoader.cpp in Sources */,

Modified: lldb/trunk/scripts/Python/build-swig-Python.sh
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/build-swig-Python.sh?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/build-swig-Python.sh (original)
+++ lldb/trunk/scripts/Python/build-swig-Python.sh Mon Sep 29 18:17:18 2014
@@ -114,6 +114,7 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/l
 " ${SRC_ROOT}/include/lldb/API/SBTarget.h"\
 " ${SRC_ROOT}/include/lldb/API/SBThread.h"\
 " ${SRC_ROOT}/include/lldb/API/SBThreadCollection.h"\
+" ${SRC_ROOT}/include/lldb/API/SBThreadPlan.h"\
 " ${SRC_ROOT}/include/lldb/API/SBType.h"\
 " ${SRC_ROOT}/include/lldb/API/SBTypeCategory.h"\
 " ${SRC_ROOT}/include/lldb/API/SBTypeFilter.h"\
@@ -163,6 +164,7 @@ INTERFACE_FILES="${SRC_ROOT}/scripts/Pyt
 " ${SRC_ROOT}/scripts/Python/interface/SBTarget.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBThread.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBThreadCollection.i"\
+" ${SRC_ROOT}/scripts/Python/interface/SBThreadPlan.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBType.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBTypeCategory.i"\
 " ${SRC_ROOT}/scripts/Python/interface/SBTypeFilter.i"\

Modified: lldb/trunk/scripts/Python/interface/SBThread.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBThread.i?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBThread.i (original)
+++ lldb/trunk/scripts/Python/interface/SBThread.i Mon Sep 29 18:17:18 2014
@@ -213,6 +213,9 @@ public:
                    uint32_t line);
 
     SBError
+    StepUsingScriptedThreadPlan (const char *script_class_name);
+
+    SBError
     JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line);
 
     void

Added: lldb/trunk/scripts/Python/interface/SBThreadPlan.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBThreadPlan.i?rev=218642&view=auto
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBThreadPlan.i (added)
+++ lldb/trunk/scripts/Python/interface/SBThreadPlan.i Mon Sep 29 18:17:18 2014
@@ -0,0 +1,123 @@
+//===-- SBThread.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBThreadPlan_h_
+#define LLDB_SBThreadPlan_h_
+
+#include "lldb/API/SBDefines.h"
+
+#include <stdio.h>
+
+namespace lldb {
+
+%feature("docstring",
+"Represents a plan for the execution control of a given thread.
+
+See also SBThread and SBFrame."
+) SBThread;
+
+class SBThreadPlan
+{
+
+friend class lldb_private::ThreadPlan;
+
+public:
+    SBThreadPlan ();
+
+    SBThreadPlan (const lldb::SBThreadPlan &threadPlan);
+    
+    SBThreadPlan (const lldb::ThreadPlanSP& lldb_object_sp);
+
+    SBThreadPlan (lldb::SBThread &thread, const char *class_name);
+
+   ~SBThreadPlan ();
+
+    bool
+    IsValid() const;
+
+    void
+    Clear ();
+
+    lldb::StopReason
+    GetStopReason();
+
+    /// Get the number of words associated with the stop reason.
+    /// See also GetStopReasonDataAtIndex().
+    size_t
+    GetStopReasonDataCount();
+
+    //--------------------------------------------------------------------------
+    /// Get information associated with a stop reason.
+    ///
+    /// Breakpoint stop reasons will have data that consists of pairs of 
+    /// breakpoint IDs followed by the breakpoint location IDs (they always come
+    /// in pairs).
+    ///
+    /// Stop Reason              Count Data Type
+    /// ======================== ===== =========================================
+    /// eStopReasonNone          0
+    /// eStopReasonTrace         0
+    /// eStopReasonBreakpoint    N     duple: {breakpoint id, location id}
+    /// eStopReasonWatchpoint    1     watchpoint id
+    /// eStopReasonSignal        1     unix signal number
+    /// eStopReasonException     N     exception data
+    /// eStopReasonExec          0
+    /// eStopReasonPlanComplete  0
+    //--------------------------------------------------------------------------
+    uint64_t
+    GetStopReasonDataAtIndex(uint32_t idx);
+
+    SBThread
+    GetThread () const;
+
+    bool
+    GetDescription (lldb::SBStream &description) const;
+
+    void
+    SetPlanComplete (bool success);
+
+    bool
+    IsPlanComplete();
+
+    bool
+    IsValid();
+
+    // This section allows an SBThreadPlan to push another of the common types of plans...
+    SBThreadPlan
+    QueueThreadPlanForStepOverRange (SBAddress &start_address,
+                                     lldb::addr_t range_size);
+
+    SBThreadPlan
+    QueueThreadPlanForStepInRange (SBAddress &start_address,
+                                   lldb::addr_t range_size);
+
+    SBThreadPlan
+    QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn = false);
+    
+    SBThreadPlan
+    QueueThreadPlanForRunToAddress (SBAddress address);
+
+
+protected:
+    friend class SBBreakpoint;
+    friend class SBBreakpointLocation;
+    friend class SBFrame;
+    friend class SBProcess;
+    friend class SBDebugger;
+    friend class SBValue;
+    friend class lldb_private::QueueImpl;
+    friend class SBQueueItem;
+
+private:
+    lldb::ThreadPlanSP m_opaque_sp;
+};
+
+} // namespace lldb
+
+#endif  // LLDB_SBThreadPlan_h_

Modified: lldb/trunk/scripts/Python/python-swigsafecast.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-swigsafecast.swig?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-swigsafecast.swig (original)
+++ lldb/trunk/scripts/Python/python-swigsafecast.swig Mon Sep 29 18:17:18 2014
@@ -45,6 +45,13 @@ SBTypeToSWIGWrapper (unsigned int* c_int
 
 template <>
 PyObject*
+SBTypeToSWIGWrapper (lldb::SBEvent* event_sb)
+{
+    return SWIG_NewPointerObj((void *) event_sb, SWIGTYPE_p_lldb__SBEvent, 0);
+}
+
+template <>
+PyObject*
 SBTypeToSWIGWrapper (lldb::SBProcess* process_sb)
 {
     return SWIG_NewPointerObj((void *) process_sb, SWIGTYPE_p_lldb__SBProcess, 0);
@@ -58,6 +65,13 @@ SBTypeToSWIGWrapper (lldb::SBThread* thr
 }
 
 template <>
+PyObject*
+SBTypeToSWIGWrapper (lldb::SBThreadPlan* thread_plan_sb)
+{
+    return SWIG_NewPointerObj((void *) thread_plan_sb, SWIGTYPE_p_lldb__SBThreadPlan, 0);
+}
+
+template <>
 PyObject*
 SBTypeToSWIGWrapper (lldb::SBTarget* target_sb)
 {

Modified: lldb/trunk/scripts/Python/python-wrapper.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-wrapper.swig?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-wrapper.swig (original)
+++ lldb/trunk/scripts/Python/python-wrapper.swig Mon Sep 29 18:17:18 2014
@@ -419,6 +419,118 @@ LLDBSwigPythonCreateSyntheticProvider
         Py_RETURN_NONE;
 }
 
+SWIGEXPORT void*
+LLDBSwigPythonCreateScriptedThreadPlan
+(
+    const char *python_class_name,
+    const char *session_dictionary_name,
+    const lldb::ThreadPlanSP& thread_plan_sp
+)
+{
+    PyObject* retval = NULL;
+
+    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
+        Py_RETURN_NONE;
+
+    // I do not want the SBThreadPlan to be deallocated when going out of scope because python
+    // has ownership of it and will manage memory for this object by itself
+    lldb::SBThreadPlan *tp_value = new lldb::SBThreadPlan(thread_plan_sp);
+
+    PyObject *ThreadPlan_PyObj = SBTypeToSWIGWrapper(tp_value);
+
+    if (ThreadPlan_PyObj == NULL)
+        Py_RETURN_NONE;
+    
+    {
+        PyErr_Cleaner py_err_cleaner(true);
+        
+        PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name, session_dictionary_name);
+        
+        if (!pfunc)
+            return retval;
+        
+        Py_INCREF(ThreadPlan_PyObj);
+        
+        PyObject* session_dict = NULL;
+        session_dict = FindSessionDictionary(session_dictionary_name);
+        retval = pfunc(tp_value, session_dict);
+
+        // FIXME: At this point we should check that the class we found supports all the methods
+        // that we need.
+        
+        Py_XINCREF (session_dict);
+        
+        Py_XINCREF(retval);
+    }
+
+    if (retval)
+        return retval;
+    else
+        Py_RETURN_NONE;
+}
+
+SWIGEXPORT bool
+LLDBSWIGPythonCallThreadPlan
+(
+    void *implementor,
+    const char *method_name,
+    lldb_private::Event *event,
+    bool &got_error
+)
+{
+    bool ret_val = false;
+    got_error = false;
+
+
+    PyErr_Cleaner py_err_cleaner(false);
+    
+    PyCallable pfunc = PyCallable::FindWithMemberFunction((PyObject *) implementor, method_name);
+    
+    if (!pfunc)
+    {
+        return ret_val;
+    }
+
+    PyObject* py_return = Py_None;
+
+    if (event != NULL)
+    {
+        lldb::SBEvent sb_event(event);
+
+        PyObject *py_obj_event = SBTypeToSWIGWrapper(sb_event);
+
+        py_return = pfunc(py_obj_event);
+    }
+    else
+    {
+        py_return = pfunc();
+    }
+
+    if (PyErr_Occurred())
+    {
+        got_error = true;
+        printf ("Return value was neither false nor true for call to %s.\n", method_name);
+        PyErr_Print();
+    }
+    else
+    {
+        if (py_return == Py_True)
+            ret_val = true;
+        else if (py_return == Py_False)
+            ret_val = false;
+        else
+        {
+            // Somebody returned the wrong thing...
+            got_error = true;
+            printf ("Wrong return value type for call to %s.\n", method_name);
+        }
+    }
+    
+    Py_XDECREF(py_return);
+
+    return ret_val;
+}
+
 // wrapper that calls an optional instance member of an object taking no arguments
 static PyObject*
 LLDBSwigPython_CallOptionalMember

Modified: lldb/trunk/scripts/lldb.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/scripts/lldb.swig (original)
+++ lldb/trunk/scripts/lldb.swig Mon Sep 29 18:17:18 2014
@@ -92,6 +92,7 @@ import os
 #include "lldb/API/SBTarget.h"
 #include "lldb/API/SBThread.h"
 #include "lldb/API/SBThreadCollection.h"
+#include "lldb/API/SBThreadPlan.h"
 #include "lldb/API/SBType.h"
 #include "lldb/API/SBTypeCategory.h"
 #include "lldb/API/SBTypeEnumMember.h"
@@ -164,6 +165,7 @@ import os
 %include "./Python/interface/SBTarget.i"
 %include "./Python/interface/SBThread.i"
 %include "./Python/interface/SBThreadCollection.i"
+%include "./Python/interface/SBThreadPlan.i"
 %include "./Python/interface/SBType.i"
 %include "./Python/interface/SBTypeCategory.i"
 %include "./Python/interface/SBTypeEnumMember.i"

Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/API/SBCommandInterpreter.cpp (original)
+++ lldb/trunk/source/API/SBCommandInterpreter.cpp Mon Sep 29 18:17:18 2014
@@ -442,6 +442,17 @@ LLDBSwigPythonCreateSyntheticProvider (c
                                        const lldb::ValueObjectSP& valobj_sp);
 
 
+extern "C" void*
+LLDBSwigPythonCreateScriptedThreadPlan (const char *python_class_name,
+                                        const char *session_dictionary_name,
+                                        const lldb::ThreadPlanSP& thread_plan_sp);
+
+extern "C" bool
+LLDBSWIGPythonCallThreadPlan (void *implementor,
+                              const char *method_name,
+                              Event *event_sp,
+                              bool &got_error);
+
 extern "C" uint32_t
 LLDBSwigPython_CalculateNumChildren (void *implementor);
 
@@ -539,7 +550,9 @@ SBCommandInterpreter::InitializeSWIG ()
                                                   LLDBSWIGPythonRunScriptKeywordThread,
                                                   LLDBSWIGPythonRunScriptKeywordTarget,
                                                   LLDBSWIGPythonRunScriptKeywordFrame,
-                                                  LLDBSWIGPython_GetDynamicSetting);
+                                                  LLDBSWIGPython_GetDynamicSetting,
+                                                  LLDBSwigPythonCreateScriptedThreadPlan,
+                                                  LLDBSWIGPythonCallThreadPlan);
 #endif
     }
 }

Modified: lldb/trunk/source/API/SBEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBEvent.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/API/SBEvent.cpp (original)
+++ lldb/trunk/source/API/SBEvent.cpp Mon Sep 29 18:17:18 2014
@@ -43,6 +43,12 @@ SBEvent::SBEvent (EventSP &event_sp) :
 {
 }
 
+SBEvent::SBEvent (Event *event_ptr) :
+    m_event_sp (),
+    m_opaque_ptr (event_ptr)
+{
+}
+
 SBEvent::SBEvent (const SBEvent &rhs) :
     m_event_sp (rhs.m_event_sp),
     m_opaque_ptr (rhs.m_opaque_ptr)

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Mon Sep 29 18:17:18 2014
@@ -41,6 +41,7 @@
 #include "lldb/API/SBEvent.h"
 #include "lldb/API/SBFrame.h"
 #include "lldb/API/SBProcess.h"
+#include "lldb/API/SBThreadPlan.h"
 #include "lldb/API/SBValue.h"
 
 using namespace lldb;
@@ -918,7 +919,9 @@ SBThread::RunToAddress (lldb::addr_t add
 
         Thread *thread = exe_ctx.GetThreadPtr();
 
-        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads));
+        ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress (abort_other_plans,
+                                                                         target_addr,
+                                                                         stop_other_threads));
 
         // This returns an error, we should use it!
         ResumeNewPlan (exe_ctx, new_plan_sp.get());
@@ -1073,6 +1076,46 @@ SBThread::StepOverUntil (lldb::SBFrame &
 }
 
 SBError
+SBThread::StepUsingScriptedThreadPlan (const char *script_class_name)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+    SBError sb_error;
+
+    Mutex::Locker api_locker;
+    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+
+    if (log)
+    {
+        log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s",
+                     static_cast<void*>(exe_ctx.GetThreadPtr()),
+                     script_class_name);
+    }
+
+
+    if (!exe_ctx.HasThreadScope())
+    {
+        sb_error.SetErrorString("this SBThread object is invalid");
+        return sb_error;
+    }
+
+    Thread *thread = exe_ctx.GetThreadPtr();
+    ThreadPlanSP thread_plan_sp = thread->QueueThreadPlanForStepScripted(false, script_class_name, false);
+
+    if (thread_plan_sp)
+        sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
+    else
+    {
+        sb_error.SetErrorStringWithFormat("Error queuing thread plan for class: %s.", script_class_name);
+        if (log)
+        log->Printf ("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing thread plan for class: %s",
+                     static_cast<void*>(exe_ctx.GetThreadPtr()),
+                     script_class_name);
+    }
+
+    return sb_error;
+}
+
+SBError
 SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line)
 {
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -1473,7 +1516,8 @@ SBThread::GetExtendedBacktraceThread (co
                                 const char *queue_name = new_thread_sp->GetQueueName();
                                 if (queue_name == NULL)
                                     queue_name = "";
-                                log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
+                                log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread "
+                                             "created (%p) with queue_id 0x%" PRIx64 " queue name '%s'",
                                              static_cast<void*>(exe_ctx.GetThreadPtr()),
                                              static_cast<void*>(new_thread_sp.get()),
                                              new_thread_sp->GetQueueID(),
@@ -1515,3 +1559,24 @@ SBThread::SafeToCallFunctions ()
         return thread_sp->SafeToCallFunctions();
     return true;
 }
+
+lldb_private::Thread *
+SBThread::operator->()
+{
+    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+    if (thread_sp)
+        return thread_sp.get();
+    else
+        return NULL;
+}
+
+lldb_private::Thread *
+SBThread::get()
+{
+    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+    if (thread_sp)
+        return thread_sp.get();
+    else
+        return NULL;
+}
+

Added: lldb/trunk/source/API/SBThreadPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThreadPlan.cpp?rev=218642&view=auto
==============================================================================
--- lldb/trunk/source/API/SBThreadPlan.cpp (added)
+++ lldb/trunk/source/API/SBThreadPlan.cpp Mon Sep 29 18:17:18 2014
@@ -0,0 +1,285 @@
+//===-- SBThread.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/API/SBThread.h"
+
+#include "lldb/API/SBSymbolContext.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredData.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/SystemRuntime.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Queue.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanPython.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
+
+
+#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBEvent.h"
+#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBThreadPlan.h"
+#include "lldb/API/SBValue.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Constructors
+//----------------------------------------------------------------------
+SBThreadPlan::SBThreadPlan ()
+{
+}
+
+SBThreadPlan::SBThreadPlan (const ThreadPlanSP& lldb_object_sp) :
+    m_opaque_sp (lldb_object_sp)
+{
+}
+
+SBThreadPlan::SBThreadPlan (const SBThreadPlan &rhs) :
+    m_opaque_sp (rhs.m_opaque_sp)
+{
+    
+}
+
+SBThreadPlan::SBThreadPlan (lldb::SBThread &sb_thread, const char *class_name)
+{
+    Thread *thread = sb_thread.get();
+    if (thread)
+        m_opaque_sp.reset(new ThreadPlanPython(*thread, class_name));
+}
+
+//----------------------------------------------------------------------
+// Assignment operator
+//----------------------------------------------------------------------
+
+const lldb::SBThreadPlan &
+SBThreadPlan::operator = (const SBThreadPlan &rhs)
+{
+    if (this != &rhs)
+        m_opaque_sp = rhs.m_opaque_sp;
+    return *this;
+}
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SBThreadPlan::~SBThreadPlan()
+{
+}
+
+lldb_private::ThreadPlan *
+SBThreadPlan::get()
+{
+    return m_opaque_sp.get();
+}
+
+bool
+SBThreadPlan::IsValid() const
+{
+    return m_opaque_sp.get() != NULL;
+}
+
+void
+SBThreadPlan::Clear ()
+{
+    m_opaque_sp.reset();
+}
+
+lldb::StopReason
+SBThreadPlan::GetStopReason()
+{
+    return eStopReasonNone;
+}
+
+size_t
+SBThreadPlan::GetStopReasonDataCount()
+{
+    return 0;
+}
+
+uint64_t
+SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx)
+{
+    return 0;
+}
+
+SBThread
+SBThreadPlan::GetThread () const
+{
+    if (m_opaque_sp)
+    {
+        return SBThread(m_opaque_sp->GetThread().shared_from_this());
+    }
+    else
+        return SBThread();
+}
+
+bool
+SBThreadPlan::GetDescription (lldb::SBStream &description) const
+{
+    if (m_opaque_sp)
+    {
+        m_opaque_sp->GetDescription(description.get(), eDescriptionLevelFull);
+    }
+    else
+    {
+        description.Printf("Empty SBThreadPlan");
+    }
+    return true;
+}
+
+void
+SBThreadPlan::SetThreadPlan (const ThreadPlanSP& lldb_object_sp)
+{
+    m_opaque_sp = lldb_object_sp;
+}
+
+void
+SBThreadPlan::SetPlanComplete (bool success)
+{
+    if (m_opaque_sp)
+        m_opaque_sp->SetPlanComplete (success);
+}
+
+bool
+SBThreadPlan::IsPlanComplete()
+{
+    if (m_opaque_sp)
+        return m_opaque_sp->IsPlanComplete();
+    else
+        return true;
+}
+
+bool
+SBThreadPlan::IsValid()
+{
+    if (m_opaque_sp)
+        return m_opaque_sp->ValidatePlan(nullptr);
+    else
+        return false;
+}
+
+    // This section allows an SBThreadPlan to push another of the common types of plans...
+    //
+    // FIXME, you should only be able to queue thread plans from inside the methods of a
+    // Scripted Thread Plan.  Need a way to enforce that.
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepOverRange (SBAddress &sb_start_address,
+                                               lldb::addr_t size)
+{
+    if (m_opaque_sp)
+    {
+        Address *start_address = sb_start_address.get();
+        if (!start_address)
+        {
+            return SBThreadPlan();
+        }
+
+        AddressRange range (*start_address, size);
+        SymbolContext sc;
+        start_address->CalculateSymbolContext(&sc);
+        return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange (false,
+                                                                                      range,
+                                                                                      sc,
+                                                                                      eAllThreads));
+    }
+    else
+    {
+        return SBThreadPlan();
+    }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepInRange (SBAddress &sb_start_address,
+                                               lldb::addr_t size)
+{
+    if (m_opaque_sp)
+    {
+        Address *start_address = sb_start_address.get();
+        if (!start_address)
+        {
+            return SBThreadPlan();
+        }
+
+        AddressRange range (*start_address, size);
+        SymbolContext sc;
+        start_address->CalculateSymbolContext(&sc);
+        return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepInRange (false,
+                                                                                      range,
+                                                                                      sc,
+                                                                                      NULL,
+                                                                                      eAllThreads));
+    }
+    else
+    {
+        return SBThreadPlan();
+    }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepOut (uint32_t frame_idx_to_step_to, bool first_insn)
+{
+    if (m_opaque_sp)
+    {
+        SymbolContext sc;
+        sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything);
+        return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForStepOut (false,
+                                                                                 &sc,
+                                                                                 first_insn,
+                                                                                 false,
+                                                                                 eVoteYes,
+                                                                                 eVoteNoOpinion,
+                                                                                 frame_idx_to_step_to));
+    }
+    else
+    {
+        return SBThreadPlan();
+    }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForRunToAddress (SBAddress sb_address)
+{
+    if (m_opaque_sp)
+    {
+        Address *address = sb_address.get();
+        if (!address)
+            return SBThreadPlan();
+
+        return SBThreadPlan (m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress (false,
+                                                                                      *address,
+                                                                                      false));
+    }
+    else
+    {
+        return SBThreadPlan();
+    }
+}
+
+

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Mon Sep 29 18:17:18 2014
@@ -46,7 +46,108 @@ using namespace lldb_private;
 // CommandObjectThreadBacktrace
 //-------------------------------------------------------------------------
 
-class CommandObjectThreadBacktrace : public CommandObjectParsed
+class CommandObjectIterateOverThreads : public CommandObjectParsed
+{
+public:
+    CommandObjectIterateOverThreads (CommandInterpreter &interpreter,
+                         const char *name,
+                         const char *help,
+                         const char *syntax,
+                         uint32_t flags) :
+        CommandObjectParsed (interpreter, name, help, syntax, flags)
+    {
+    }
+
+    virtual ~CommandObjectIterateOverThreads() {}
+    virtual bool
+    DoExecute (Args& command, CommandReturnObject &result)
+    {        
+        result.SetStatus (m_success_return);
+
+        if (command.GetArgumentCount() == 0)
+        {
+            Thread *thread = m_exe_ctx.GetThreadPtr();
+            if (!HandleOneThread (*thread, result))
+                return false;
+        }
+        else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
+        {
+            Process *process = m_exe_ctx.GetProcessPtr();
+            uint32_t idx = 0;
+            for (ThreadSP thread_sp : process->Threads())
+            {
+                if (idx != 0 && m_add_return)
+                    result.AppendMessage("");
+
+                if (!HandleOneThread(*(thread_sp.get()), result))
+                    return false;
+                ++idx;
+            }
+        }
+        else
+        {
+            const size_t num_args = command.GetArgumentCount();
+            Process *process = m_exe_ctx.GetProcessPtr();
+            Mutex::Locker locker (process->GetThreadList().GetMutex());
+            std::vector<ThreadSP> thread_sps;
+
+            for (size_t i = 0; i < num_args; i++)
+            {
+                bool success;
+                
+                uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
+                if (!success)
+                {
+                    result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+                
+                thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
+                
+                if (!thread_sps[i])
+                {
+                    result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
+                    result.SetStatus (eReturnStatusFailed);
+                    return false;
+                }
+                
+            }
+            
+            for (uint32_t i = 0; i < num_args; i++)
+            {
+                if (!HandleOneThread (*(thread_sps[i].get()), result))
+                    return false;
+
+                if (i < num_args - 1 && m_add_return)
+                    result.AppendMessage("");
+            }
+        }
+        return result.Succeeded();
+    }
+
+protected:
+
+    // Override this to do whatever you need to do for one thread.
+    //
+    // If you return false, the iteration will stop, otherwise it will proceed.
+    // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
+    // so you only need to set the return status in HandleOneThread if you want to indicate an error.
+    // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
+
+    virtual bool
+    HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
+
+    ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
+    bool m_add_return = true;
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadBacktrace
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
 {
 public:
 
@@ -134,7 +235,7 @@ public:
     };
 
     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
-        CommandObjectParsed (interpreter,
+        CommandObjectIterateOverThreads (interpreter,
                              "thread backtrace",
                              "Show the stack for one or more threads.  If no threads are specified, show the currently selected thread.  Use the thread-index \"all\" to see all threads.",
                              NULL,
@@ -145,18 +246,6 @@ public:
                              eFlagProcessMustBePaused   ),
         m_options(interpreter)
     {
-        CommandArgumentEntry arg;
-        CommandArgumentData thread_idx_arg;
-        
-        // Define the first (and only) variant of this arg.
-        thread_idx_arg.arg_type = eArgTypeThreadIndex;
-        thread_idx_arg.arg_repetition = eArgRepeatStar;
-        
-        // There is only one variant this argument could be; put it into the argument entry.
-        arg.push_back (thread_idx_arg);
-        
-        // Push the data for the first argument into the m_arguments vector.
-        m_arguments.push_back (arg);
     }
 
     ~CommandObjectThreadBacktrace()
@@ -197,106 +286,28 @@ protected:
     }
 
     virtual bool
-    DoExecute (Args& command, CommandReturnObject &result)
-    {        
-        result.SetStatus (eReturnStatusSuccessFinishResult);
+    HandleOneThread (Thread &thread, CommandReturnObject &result)
+    {
         Stream &strm = result.GetOutputStream();
 
         // Don't show source context when doing backtraces.
         const uint32_t num_frames_with_source = 0;
-        if (command.GetArgumentCount() == 0)
-        {
-            Thread *thread = m_exe_ctx.GetThreadPtr();
-            // Thread::GetStatus() returns the number of frames shown.
-            if (thread->GetStatus (strm,
+
+        if (!thread.GetStatus (strm,
                                    m_options.m_start,
                                    m_options.m_count,
                                    num_frames_with_source))
-            {
-                result.SetStatus (eReturnStatusSuccessFinishResult);
-                if (m_options.m_extended_backtrace)
-                {
-                    DoExtendedBacktrace (thread, result);
-                }
-            }
-        }
-        else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
         {
-            Process *process = m_exe_ctx.GetProcessPtr();
-            uint32_t idx = 0;
-            for (ThreadSP thread_sp : process->Threads())
-            {
-                if (idx != 0)
-                    result.AppendMessage("");
-
-                if (!thread_sp->GetStatus (strm,
-                                           m_options.m_start,
-                                           m_options.m_count,
-                                           num_frames_with_source))
-                {
-                    result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                if (m_options.m_extended_backtrace)
-                {
-                    DoExtendedBacktrace (thread_sp.get(), result);
-                }
-                
-                ++idx;
-            }
+            result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
         }
-        else
+        if (m_options.m_extended_backtrace)
         {
-            const size_t num_args = command.GetArgumentCount();
-            Process *process = m_exe_ctx.GetProcessPtr();
-            Mutex::Locker locker (process->GetThreadList().GetMutex());
-            std::vector<ThreadSP> thread_sps;
-
-            for (size_t i = 0; i < num_args; i++)
-            {
-                bool success;
-                
-                uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
-                if (!success)
-                {
-                    result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                
-                thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
-                
-                if (!thread_sps[i])
-                {
-                    result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                
-            }
-            
-            for (uint32_t i = 0; i < num_args; i++)
-            {
-                if (!thread_sps[i]->GetStatus (strm,
-                                               m_options.m_start,
-                                               m_options.m_count,
-                                               num_frames_with_source))
-                {
-                    result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                if (m_options.m_extended_backtrace)
-                {
-                    DoExtendedBacktrace (thread_sps[i].get(), result);
-                }
-                
-                if (i < num_args - 1)
-                    result.AppendMessage("");
-            }
+            DoExtendedBacktrace (&thread, result);
         }
-        return result.Succeeded();
+
+        return true;
     }
 
     CommandOptions m_options;
@@ -379,6 +390,12 @@ public:
                     break;
                 }
                 break;
+            case 'C':
+                {
+                    m_class_name.clear();
+                    m_class_name.assign(option_arg);
+                }
+                break;
             case 'm':
                 {
                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
@@ -416,6 +433,7 @@ public:
             m_run_mode = eOnlyDuringStepping;
             m_avoid_regexp.clear();
             m_step_in_target.clear();
+            m_class_name.clear();
             m_step_count = 1;
         }
 
@@ -435,6 +453,7 @@ public:
         RunMode m_run_mode;
         std::string m_avoid_regexp;
         std::string m_step_in_target;
+        std::string m_class_name;
         int32_t m_step_count;
     };
 
@@ -520,6 +539,22 @@ protected:
             }
         }
 
+        if (m_step_type == eStepTypeScripted)
+        {
+            if (m_options.m_class_name.empty())
+            {
+                result.AppendErrorWithFormat ("empty class name for scripted step.");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+            else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
+            {
+                result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+        }
+
         const bool abort_other_plans = false;
         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
         
@@ -530,7 +565,7 @@ protected:
             bool_stop_other_threads = false;
         else if (m_options.m_run_mode == eOnlyDuringStepping)
         {
-            if (m_step_type == eStepTypeOut)
+            if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
                 bool_stop_other_threads = false;
             else
                 bool_stop_other_threads = true;
@@ -599,6 +634,12 @@ protected:
                                                           thread->GetSelectedFrameIndex(),
                                                           m_options.m_step_out_avoid_no_debug);
         }
+        else if (m_step_type == eStepTypeScripted)
+        {
+            new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
+                                                                  m_options.m_class_name.c_str(),
+                                                                  bool_stop_other_threads);
+        }
         else
         {
             result.AppendError ("step type is not supported");
@@ -686,10 +727,11 @@ CommandObjectThreadStepWithTypeAndScope:
 {
 { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether stepping into functions will step over functions with no debug information."},
 { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug",  'A', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."},
-{ LLDB_OPT_SET_1, false, "count",           'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
-{ LLDB_OPT_SET_1, false, "run-mode",        'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
-{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
-{ LLDB_OPT_SET_1, false, "step-in-target",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
+{ LLDB_OPT_SET_1, false, "count",                     'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
+{ LLDB_OPT_SET_1, false, "run-mode",                  'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
+{ LLDB_OPT_SET_1, false, "step-over-regexp",          'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
+{ LLDB_OPT_SET_1, false, "step-in-target",            't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
+{ LLDB_OPT_SET_2, false, "python-class",              'C', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."},
 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
 };
 
@@ -1358,32 +1400,22 @@ protected:
 // CommandObjectThreadInfo
 //-------------------------------------------------------------------------
 
-class CommandObjectThreadInfo : public CommandObjectParsed
+class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
 {
 public:
 
     CommandObjectThreadInfo (CommandInterpreter &interpreter) :
-        CommandObjectParsed (interpreter, 
-                             "thread info",
-                             "Show an extended summary of information about thread(s) in a process.",
-                             "thread info",
-                             eFlagRequiresProcess       |
-                             eFlagTryTargetAPILock      |
-                             eFlagProcessMustBeLaunched |
-                             eFlagProcessMustBePaused),
+        CommandObjectIterateOverThreads (interpreter,
+                                         "thread info",
+                                         "Show an extended summary of information about thread(s) in a process.",
+                                         "thread info",
+                                         eFlagRequiresProcess       |
+                                         eFlagTryTargetAPILock      |
+                                         eFlagProcessMustBeLaunched |
+                                         eFlagProcessMustBePaused),
         m_options (interpreter)
     {
-        CommandArgumentEntry arg;
-        CommandArgumentData thread_idx_arg;
-        
-        thread_idx_arg.arg_type = eArgTypeThreadIndex;
-        thread_idx_arg.arg_repetition = eArgRepeatStar;
-        
-        // There is only one variant this argument could be; put it into the argument entry.
-        arg.push_back (thread_idx_arg);
-        
-        // Push the data for the first argument into the m_arguments vector.
-        m_arguments.push_back (arg);
+        m_add_return = false;
     }
 
     class CommandOptions : public Options
@@ -1451,81 +1483,16 @@ public:
     }
 
     virtual bool
-    DoExecute (Args& command, CommandReturnObject &result)
+    HandleOneThread (Thread &thread, CommandReturnObject &result)
     {
-        result.SetStatus (eReturnStatusSuccessFinishResult);
         Stream &strm = result.GetOutputStream();
-
-        if (command.GetArgumentCount() == 0)
+        if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
         {
-            Thread *thread = m_exe_ctx.GetThreadPtr();
-            if (thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
-            {
-                result.SetStatus (eReturnStatusSuccessFinishResult);
-            }
-        }
-        else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
-        {
-            Process *process = m_exe_ctx.GetProcessPtr();
-            uint32_t idx = 0;
-            for (ThreadSP thread_sp : process->Threads())
-            {
-                if (idx != 0)
-                    result.AppendMessage("");
-                if (!thread_sp->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
-                {
-                    result.AppendErrorWithFormat ("error displaying info for thread: \"0x%4.4x\"\n", idx);
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                ++idx;
-            }
-        }
-        else
-        {
-            const size_t num_args = command.GetArgumentCount();
-            Process *process = m_exe_ctx.GetProcessPtr();
-            Mutex::Locker locker (process->GetThreadList().GetMutex());
-            std::vector<ThreadSP> thread_sps;
-
-            for (size_t i = 0; i < num_args; i++)
-            {
-                bool success;
-                
-                uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
-                if (!success)
-                {
-                    result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                
-                thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
-                
-                if (!thread_sps[i])
-                {
-                    result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                
-            }
-            
-            for (uint32_t i = 0; i < num_args; i++)
-            {
-                if (!thread_sps[i]->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
-                {
-                    result.AppendErrorWithFormat ("error displaying info for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                
-                if (i < num_args - 1)
-                    result.AppendMessage("");
-            }
-
+            result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
         }
-        return result.Succeeded();
+        return true;
     }
 
     CommandOptions m_options;
@@ -1958,6 +1925,228 @@ CommandObjectThreadJump::CommandOptions:
 };
 
 //-------------------------------------------------------------------------
+// Next are the subcommands of CommandObjectMultiwordThreadPlan
+//-------------------------------------------------------------------------
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadPlanList
+//-------------------------------------------------------------------------
+class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
+{
+public:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions (CommandInterpreter &interpreter) :
+            Options(interpreter)
+        {
+            // Keep default values of all options in one place: OptionParsingStarting ()
+            OptionParsingStarting ();
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            const int short_option = m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+                case 'i':
+                {
+                    m_internal = true;
+                }
+                break;
+                case 'v':
+                {
+                    m_verbose = true;
+                }
+                break;
+                default:
+                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+                    break;
+
+            }
+            return error;
+        }
+
+        void
+        OptionParsingStarting ()
+        {
+            m_verbose = false;
+            m_internal = false;
+        }
+
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+        bool m_verbose;
+        bool m_internal;
+    };
+
+    CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
+        CommandObjectIterateOverThreads (interpreter,
+                                         "thread plan list",
+                                         "Show thread plans for one or more threads.  If no threads are specified, show the "
+                                         "currently selected thread.  Use the thread-index \"all\" to see all threads.",
+                                         NULL,
+                                         eFlagRequiresProcess       |
+                                         eFlagRequiresThread        |
+                                         eFlagTryTargetAPILock      |
+                                         eFlagProcessMustBeLaunched |
+                                         eFlagProcessMustBePaused   ),
+        m_options(interpreter)
+    {
+    }
+
+    ~CommandObjectThreadPlanList ()
+    {
+    }
+
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+protected:
+    virtual bool
+    HandleOneThread (Thread &thread, CommandReturnObject &result)
+    {
+        Stream &strm = result.GetOutputStream();
+        DescriptionLevel desc_level = eDescriptionLevelFull;
+        if (m_options.m_verbose)
+            desc_level = eDescriptionLevelVerbose;
+
+        thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
+        return true;
+    }
+    CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
+{ LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
+{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectThreadPlanDiscard : public CommandObjectParsed
+{
+public:
+    CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
+        CommandObjectParsed (interpreter,
+                             "thread plan discard",
+                             "Discards thread plans up to and including the plan passed as the command argument."
+                             "Only user visible plans can be discarded, use the index from \"thread plan list\""
+                             " without the \"-i\" argument.",
+                             NULL,
+                             eFlagRequiresProcess       |
+                             eFlagRequiresThread        |
+                             eFlagTryTargetAPILock      |
+                             eFlagProcessMustBeLaunched |
+                             eFlagProcessMustBePaused   )
+    {
+        CommandArgumentEntry arg;
+        CommandArgumentData plan_index_arg;
+
+        // Define the first (and only) variant of this arg.
+        plan_index_arg.arg_type = eArgTypeUnsignedInteger;
+        plan_index_arg.arg_repetition = eArgRepeatPlain;
+
+        // There is only one variant this argument could be; put it into the argument entry.
+        arg.push_back (plan_index_arg);
+
+        // Push the data for the first argument into the m_arguments vector.
+        m_arguments.push_back (arg);
+    }
+
+    virtual ~CommandObjectThreadPlanDiscard () {}
+
+    bool
+    DoExecute (Args& args, CommandReturnObject &result)
+    {
+        Thread *thread = m_exe_ctx.GetThreadPtr();
+        if (args.GetArgumentCount() != 1)
+        {
+            result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
+                                         args.GetArgumentCount());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        bool success;
+        uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
+        if (!success)
+        {
+            result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
+                                         args.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        if (thread_plan_idx == 0)
+        {
+            result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
+        {
+            result.SetStatus(eReturnStatusSuccessFinishNoResult);
+            return true;
+        }
+        else
+        {
+            result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
+                                         args.GetArgumentAtIndex(0));
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+    }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordThreadPlan
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
+{
+public:
+    CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
+        CommandObjectMultiword (interpreter,
+                                "plan",
+                                "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
+                                "thread plan <subcommand> [<subcommand objects]")
+    {
+        LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
+        LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
+    }
+
+    virtual ~CommandObjectMultiwordThreadPlan () {}
+
+
+};
+
+//-------------------------------------------------------------------------
 // CommandObjectMultiwordThread
 //-------------------------------------------------------------------------
 
@@ -2014,6 +2203,16 @@ CommandObjectMultiwordThread::CommandObj
                                                     NULL,
                                                     eStepTypeTraceOver,
                                                     eStepScopeInstruction)));
+
+    LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
+                                                    interpreter,
+                                                    "thread step-scripted",
+                                                    "Step as instructed by the script class passed in the -C option.",
+                                                    NULL,
+                                                    eStepTypeScripted,
+                                                    eStepScopeSource)));
+
+    LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
 }
 
 CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Mon Sep 29 18:17:18 2014
@@ -422,7 +422,7 @@ ClangFunction::InsertFunction (Execution
     return true;
 }
 
-ThreadPlan *
+lldb::ThreadPlanSP
 ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, 
                                             lldb::addr_t args_addr,
                                             const EvaluateExpressionOptions &options,
@@ -447,14 +447,14 @@ ClangFunction::GetThreadPlanToCallFuncti
     
     lldb::addr_t args = { args_addr };
     
-    ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread, 
+    lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread,
                                                        wrapper_address,
                                                        ClangASTType(),
                                                        args,
-                                                       options);
-    new_plan->SetIsMasterPlan(true);
-    new_plan->SetOkayToDiscard (false);
-    return new_plan;
+                                                       options));
+    new_plan_sp->SetIsMasterPlan(true);
+    new_plan_sp->SetOkayToDiscard (false);
+    return new_plan_sp;
 }
 
 bool
@@ -541,10 +541,10 @@ ClangFunction::ExecuteFunction(
     if (log)
         log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
     
-    lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx,
-                                                                  args_addr,
-                                                                  real_options,
-                                                                  errors));
+    lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx,
+                                                                   args_addr,
+                                                                   real_options,
+                                                                   errors);
     if (!call_plan_sp)
         return lldb::eExpressionSetupError;
         

Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Mon Sep 29 18:17:18 2014
@@ -885,17 +885,17 @@ ClangUserExpression::Execute (Stream &er
 
             args.push_back(struct_address);
          
-            ThreadPlanCallUserExpression *user_expression_plan = 
-                    new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
-                                                      wrapper_address, 
-                                                      args,
-                                                      options,
-                                                      shared_ptr_to_me);
-            lldb::ThreadPlanSP call_plan_sp(user_expression_plan);
+            lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
+                                                                              wrapper_address,
+                                                                              args,
+                                                                              options,
+                                                                              shared_ptr_to_me));
 
             if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
                 return lldb::eExpressionSetupError;
 
+            ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
             lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
 
             function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();

Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Mon Sep 29 18:17:18 2014
@@ -131,7 +131,9 @@ ScriptInterpreter::InitializeInterpreter
                                           SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
                                           SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
                                           SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
-                                          SWIGPython_GetDynamicSetting swig_plugin_get)
+                                          SWIGPython_GetDynamicSetting swig_plugin_get,
+                                          SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+                                          SWIGPythonCallThreadPlan swig_call_thread_plan)
 {
 #ifndef LLDB_DISABLE_PYTHON
     ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback,
@@ -153,6 +155,8 @@ ScriptInterpreter::InitializeInterpreter
                                                     swig_run_script_keyword_thread,
                                                     swig_run_script_keyword_target,
                                                     swig_run_script_keyword_frame,
-                                                    swig_plugin_get);
+                                                    swig_plugin_get,
+                                                    swig_thread_plan_script,
+                                                    swig_call_thread_plan);
 #endif // #ifndef LLDB_DISABLE_PYTHON
 }

Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Mon Sep 29 18:17:18 2014
@@ -37,6 +37,7 @@
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/PythonDataObjects.h"
 #include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -62,6 +63,8 @@ static ScriptInterpreter::SWIGPythonScri
 static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr;
 static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr;
 static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr;
+static ScriptInterpreter::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr;
+static ScriptInterpreter::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr;
 
 static std::string
 ReadPythonBacktrace (PyObject* py_backtrace);
@@ -1617,6 +1620,87 @@ ScriptInterpreterPython::OSPlugin_Create
 }
 
 lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::CreateScriptedThreadPlan (const char *class_name,
+                              lldb::ThreadPlanSP thread_plan_sp)
+{
+    if (class_name == nullptr || class_name[0] == '\0')
+        return lldb::ScriptInterpreterObjectSP();
+    
+    if (!thread_plan_sp.get())
+        return lldb::ScriptInterpreterObjectSP();
+
+    Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
+    ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+    ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter);
+    
+    if (!script_interpreter)
+        return lldb::ScriptInterpreterObjectSP();
+    
+    void* ret_val;
+
+    {
+        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+        
+        ret_val = g_swig_thread_plan_script (class_name,
+                                             python_interpreter->m_dictionary_name.c_str(),
+                                             thread_plan_sp);
+    }
+    
+    return MakeScriptObject(ret_val);
+}
+
+bool
+ScriptInterpreterPython::ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                Event *event,
+                                bool &script_error)
+{
+    bool explains_stop = true;
+    if (implementor_sp)
+    {
+        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+        explains_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "explains_stop", event, script_error);
+        if (script_error)
+            return true;
+    }
+    return explains_stop;
+}
+
+bool
+ScriptInterpreterPython::ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp,
+                              Event *event,
+                              bool &script_error)
+{
+    bool should_stop = true;
+    if (implementor_sp)
+    {
+        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+        should_stop = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_stop", event, script_error);
+        if (script_error)
+            return true;
+    }
+    return should_stop;
+}
+
+lldb::StateType
+ScriptInterpreterPython::ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp,
+                                                        bool &script_error)
+{
+    bool should_step = false;
+    if (implementor_sp)
+    {
+        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+        should_step = g_swig_call_thread_plan (implementor_sp->GetObject(), "should_step", NULL, script_error);
+        if (script_error)
+            should_step = true;
+    }
+    if (should_step)
+        return lldb::eStateStepping;
+    else
+        return lldb::eStateRunning;
+}
+
+
+lldb::ScriptInterpreterObjectSP
 ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec,
                                            lldb_private::Error& error)
 {
@@ -2536,7 +2620,9 @@ ScriptInterpreterPython::InitializeInter
                                                 SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
                                                 SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
                                                 SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
-                                                SWIGPython_GetDynamicSetting swig_plugin_get)
+                                                SWIGPython_GetDynamicSetting swig_plugin_get,
+                                                SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+                                                SWIGPythonCallThreadPlan swig_call_thread_plan)
 {
     g_swig_init_callback = swig_init_callback;
     g_swig_breakpoint_callback = swig_breakpoint_callback;
@@ -2558,6 +2644,8 @@ ScriptInterpreterPython::InitializeInter
     g_swig_run_script_keyword_target = swig_run_script_keyword_target;
     g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
     g_swig_plugin_get = swig_plugin_get;
+    g_swig_thread_plan_script = swig_thread_plan_script;
+    g_swig_call_thread_plan = swig_call_thread_plan;
 }
 
 void

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Mon Sep 29 18:17:18 2014
@@ -89,10 +89,10 @@ AppleThreadPlanStepThroughObjCTrampoline
         options.SetIgnoreBreakpoints(true);
         options.SetStopOthers(m_stop_others);
         m_thread.CalculateExecutionContext(exc_ctx);
-        m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
-                                                                      m_args_addr,
-                                                                      options,
-                                                                      errors));
+        m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
+                                                                  m_args_addr,
+                                                                  options,
+                                                                  errors);
         m_func_sp->SetOkayToDiscard(true);
         m_thread.QueueThreadPlan (m_func_sp, false);
     }

Modified: lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp Mon Sep 29 18:17:18 2014
@@ -98,13 +98,11 @@ lldb_private::InferiorCallMmap (Process
                 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
                 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
                 lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
-                ThreadPlanCallFunction *call_function_thread_plan
-                  = new ThreadPlanCallFunction (*thread,
-                                                mmap_range.GetBaseAddress(),
-                                                clang_void_ptr_type,
-                                                args,
-                                                options);
-                lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+                                                                             mmap_range.GetBaseAddress(),
+                                                                             clang_void_ptr_type,
+                                                                             args,
+                                                                             options));
                 if (call_plan_sp)
                 {
                     StreamFile error_strm;
@@ -241,13 +239,11 @@ lldb_private::InferiorCall (Process *pro
 
     ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
     ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
-    ThreadPlanCallFunction *call_function_thread_plan
-        = new ThreadPlanCallFunction (*thread,
-                                      *address,
-                                      clang_void_ptr_type,
-                                      llvm::ArrayRef<addr_t>(),
-                                      options);
-    lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+    lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+                                                                 *address,
+                                                                 clang_void_ptr_type,
+                                                                 llvm::ArrayRef<addr_t>(),
+                                                                 options));
     if (call_plan_sp)
     {
         StreamString error_strm;

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Mon Sep 29 18:17:18 2014
@@ -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 @@ Thread::SetupForResume ()
 
                 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 @@ Thread::SetTracer (lldb::ThreadPlanTrace
         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 @@ Thread::QueueThreadPlanForStepInRange
     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 @@ Thread::QueueThreadPlanForStepOutNoShoul
     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 @@ Thread::QueueThreadPlanForStepUntil (boo
 
 }
 
+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++);
+        }
     }
+}
 
-    stack_size = m_completed_plan_stack.size();
-    if (stack_size > 0)
+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)
     {
-        s->Indent();
-        s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
-        for (i = stack_size - 1; i >= 0; i--)
+        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 ("Element %d: ", i);
-            m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
-            s->EOL();
+            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:\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

Added: lldb/trunk/source/Target/ThreadPlanPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanPython.cpp?rev=218642&view=auto
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanPython.cpp (added)
+++ lldb/trunk/source/Target/ThreadPlanPython.cpp Mon Sep 29 18:17:18 2014
@@ -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;
+}

Modified: lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInRange.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInRange.cpp Mon Sep 29 18:17:18 2014
@@ -128,17 +128,31 @@ void
 ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
     if (level == lldb::eDescriptionLevelBrief)
+    {
         s->Printf("step in");
-    else
+        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 ("Stepping through range (stepping into functions): ");
+        s->Printf (" using ranges:");
         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->PutChar('.');
 }
 
 bool
@@ -303,6 +317,7 @@ ThreadPlanStepInRange::ShouldStop (Event
     else
     {
         m_no_more_plans = false;
+        m_sub_plan_sp->SetPrivate(true);
         return false;
     }
 }

Modified: lldb/trunk/source/Target/ThreadPlanStepOut.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOut.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepOut.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepOut.cpp Mon Sep 29 18:17:18 2014
@@ -54,7 +54,6 @@ ThreadPlanStepOut::ThreadPlanStepOut
     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 @@ ThreadPlanStepOut::ThreadPlanStepOut
                                                             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 @@ ThreadPlanStepOut::GetDescription (Strea
         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 @@ ThreadPlanStepOut::QueueInlinedStepPlan
                 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 @@ ThreadPlanStepOut::QueueInlinedStepPlan
                     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;

Modified: lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp Mon Sep 29 18:17:18 2014
@@ -62,12 +62,26 @@ void
 ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
     if (level == lldb::eDescriptionLevelBrief)
+    {
         s->Printf("step over");
-    else
+        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 ("stepping through range (stepping over functions): ");
-        DumpRanges(s);    
+        s->Printf (" using ranges: ");
+        DumpRanges(s);
     }
+
+    s->PutChar('.');
 }
 
 void
@@ -317,11 +331,15 @@ ThreadPlanStepOverRange::ShouldStop (Eve
     {
         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)
     {

Modified: lldb/trunk/source/Target/ThreadPlanStepRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepRange.cpp?rev=218642&r1=218641&r2=218642&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepRange.cpp Mon Sep 29 18:17:18 2014
@@ -44,7 +44,8 @@ ThreadPlanStepRange::ThreadPlanStepRange
                                           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 @@ ThreadPlanStepRange::ThreadPlanStepRange
     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 @@ ThreadPlanStepRange::InRange ()
             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();





More information about the lldb-commits mailing list