[Lldb-commits] [lldb] r203747 - This commit reworks how the thread plan's ShouldStopHere mechanism works, so that it is useful not only

Jim Ingham jingham at apple.com
Wed Mar 12 19:47:15 PDT 2014


Author: jingham
Date: Wed Mar 12 21:47:14 2014
New Revision: 203747

URL: http://llvm.org/viewvc/llvm-project?rev=203747&view=rev
Log:
This commit reworks how the thread plan's ShouldStopHere mechanism works, so that it is useful not only
for customizing "step-in" behavior (e.g. step-in doesn't step into code with no debug info), but also 
the behavior of step-in/step-out and step-over when they step out of the frame they started in.

I also added as a proof of concept of this reworking a mode for stepping where stepping out of a frame
into a frame with no debug information will continue stepping out till it arrives at a frame that does
have debug information.  This is useful when you are debugging callback based code where the callbacks
are separated from the code that initiated them by some library glue you don't care about, among other
things.

Modified:
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/include/lldb/Target/ThreadPlanShouldStopHere.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
    lldb/trunk/include/lldb/lldb-private-interfaces.h
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Core/IOHandler.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlanShouldStopHere.cpp
    lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
    lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
    lldb/trunk/source/Target/ThreadPlanStepOut.cpp
    lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
    lldb/trunk/test/make/Makefile.rules

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Wed Mar 12 21:47:14 2014
@@ -49,6 +49,12 @@ public:
     
     bool
     GetTraceEnabledState() const;
+    
+    bool
+    GetStepInAvoidsNoDebug () const;
+    
+    bool
+    GetStepOutAvoidsNoDebug () const;
 };
 
 typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP;
@@ -440,17 +446,22 @@ public:
     ///     If true and the frame has debug info, then do a source level
     ///     step in, else do a single instruction step in.
     ///
-    /// @param[in] avoid_code_without_debug_info
+    /// @param[in] step_in_avoids_code_without_debug_info
     ///     If \a true, then avoid stepping into code that doesn't have
     ///     debug info, else step into any code regardless of wether it
     ///     has debug info.
     ///
+    /// @param[in] step_out_avoids_code_without_debug_info
+    ///     If \a true, then if you step out to code with no debug info, keep
+    ///     stepping out till you get to code with debug info.
+    ///
     /// @return
     ///     An error that describes anything that went wrong
     //------------------------------------------------------------------
     virtual Error
     StepIn (bool source_step,
-            bool avoid_code_without_debug_info);
+            LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
+            LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
 
     //------------------------------------------------------------------
     /// Default implementation for stepping over.
@@ -466,7 +477,8 @@ public:
     ///     An error that describes anything that went wrong
     //------------------------------------------------------------------
     virtual Error
-    StepOver (bool source_step);
+    StepOver (bool source_step,
+              LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
 
     //------------------------------------------------------------------
     /// Default implementation for stepping out.
@@ -592,14 +604,19 @@ public:
     /// @param[in] stop_other_threads
     ///    \b true if we will stop other threads while we single step this one.
     ///
+    /// @param[in] step_out_avoids_code_without_debug_info
+    ///    If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info.
+    ///    If eLazyBoolCalculate, we will consult the default set in the thread.
+    ///
     /// @return
     ///     A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
     //------------------------------------------------------------------
     virtual lldb::ThreadPlanSP
     QueueThreadPlanForStepOverRange (bool abort_other_plans,
-                                 const AddressRange &range,
-                                 const SymbolContext &addr_context,
-                                 lldb::RunMode stop_other_threads);
+                                     const AddressRange &range,
+                                     const SymbolContext &addr_context,
+                                     lldb::RunMode stop_other_threads,
+                                     LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
 
     //------------------------------------------------------------------
     /// Queues the plan used to step through an address range, stepping into functions.
@@ -627,19 +644,25 @@ public:
     /// @param[in] stop_other_threads
     ///    \b true if we will stop other threads while we single step this one.
     ///
-    /// @param[in] avoid_code_without_debug_info
-    ///    If \b true we will step out if we step into code with no debug info.
+    /// @param[in] step_in_avoids_code_without_debug_info
+    ///    If eLazyBoolYes we will step out if we step into code with no debug info.
+    ///    If eLazyBoolCalculate we will consult the default set in the thread.
+    ///
+    /// @param[in] step_out_avoids_code_without_debug_info
+    ///    If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info.
+    ///    If eLazyBoolCalculate, it will consult the default set in the thread.
     ///
     /// @return
     ///     A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
     //------------------------------------------------------------------
     virtual lldb::ThreadPlanSP
     QueueThreadPlanForStepInRange (bool abort_other_plans,
-                                 const AddressRange &range,
-                                 const SymbolContext &addr_context,
-                                 const char *step_in_target,
-                                 lldb::RunMode stop_other_threads,
-                                 bool avoid_code_without_debug_info);
+                                   const AddressRange &range,
+                                   const SymbolContext &addr_context,
+                                   const char *step_in_target,
+                                   lldb::RunMode stop_other_threads,
+                                   LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
+                                   LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
 
     //------------------------------------------------------------------
     /// Queue the plan used to step out of the function at the current PC of
@@ -666,6 +689,10 @@ public:
     /// @param[in] run_vote
     ///    See standard meanings for the stop & run votes in ThreadPlan.h.
     ///
+    /// @param[in] step_out_avoids_code_without_debug_info
+    ///    If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info.
+    ///    If eLazyBoolCalculate, it will consult the default set in the thread.
+    ///
     /// @return
     ///     A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
     //------------------------------------------------------------------
@@ -676,7 +703,46 @@ public:
                                bool stop_other_threads,
                                Vote stop_vote, // = eVoteYes,
                                Vote run_vote, // = eVoteNoOpinion);
-                               uint32_t frame_idx);
+                               uint32_t frame_idx,
+                               LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+
+    //------------------------------------------------------------------
+    /// Queue the plan used to step out of the function at the current PC of
+    /// a thread.  This version does not consult the should stop here callback, and should only
+    /// be used by other thread plans when they need to retain control of the step out.
+    ///
+    /// @param[in] abort_other_plans
+    ///    \b true if we discard the currently queued plans and replace them with this one.
+    ///    Otherwise this plan will go on the end of the plan stack.
+    ///
+    /// @param[in] addr_context
+    ///    When dealing with stepping through inlined functions the current PC is not enough information to know
+    ///    what "step" means.  For instance a series of nested inline functions might start at the same address.
+    //     The \a addr_context provides the current symbol context the step
+    ///    is supposed to be out of.
+    //   FIXME: Currently unused.
+    ///
+    /// @param[in] first_insn
+    ///     \b true if this is the first instruction of a function.
+    ///
+    /// @param[in] stop_other_threads
+    ///    \b true if we will stop other threads while we single step this one.
+    ///
+    /// @param[in] stop_vote
+    /// @param[in] run_vote
+    ///    See standard meanings for the stop & run votes in ThreadPlan.h.
+    ///
+    /// @return
+    ///     A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+    //------------------------------------------------------------------
+    virtual lldb::ThreadPlanSP
+    QueueThreadPlanForStepOutNoShouldStop (bool abort_other_plans,
+                                           SymbolContext *addr_context,
+                                           bool first_insn,
+                                           bool stop_other_threads,
+                                           Vote stop_vote, // = eVoteYes,
+                                           Vote run_vote, // = eVoteNoOpinion);
+                                           uint32_t frame_idx);
 
     //------------------------------------------------------------------
     /// Gets the plan used to step through the code that steps from a function

Modified: lldb/trunk/include/lldb/Target/ThreadPlanShouldStopHere.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanShouldStopHere.h?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanShouldStopHere.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanShouldStopHere.h Wed Mar 12 21:47:14 2014
@@ -21,8 +21,9 @@ namespace lldb_private {
 // This is an interface that ThreadPlans can adopt to allow flexible modifications of the behavior
 // when a thread plan comes to a place where it would ordinarily stop.  If such modification makes
 // sense for your plan, inherit from this class, and when you would be about to stop (in your ShouldStop
-// method), call InvokeShouldStopHereCallback, and if that returns a non-NULL plan, execute that
-// plan instead of stopping.
+// method), call InvokeShouldStopHereCallback, passing in the frame comparision between where the step operation
+// started and where you arrived.  If it returns true, then QueueStepOutFromHere will queue the plan
+// to execute instead of stopping.
 //
 // The classic example of the use of this is ThreadPlanStepInRange not stopping in frames that have
 // no debug information.
@@ -34,27 +35,84 @@ namespace lldb_private {
 class ThreadPlanShouldStopHere
 {
 public:
+    struct ThreadPlanShouldStopHereCallbacks
+    {
+        ThreadPlanShouldStopHereCallbacks()
+        {
+            should_stop_here_callback = nullptr;
+            step_from_here_callback = nullptr;
+        }
+        
+        ThreadPlanShouldStopHereCallbacks(ThreadPlanShouldStopHereCallback should_stop,
+                                          ThreadPlanStepFromHereCallback step_from_here)
+        {
+            should_stop_here_callback = should_stop;
+            step_from_here_callback = step_from_here;
+        }
+        
+        void
+        Clear()
+        {
+            should_stop_here_callback = nullptr;
+            step_from_here_callback = nullptr;
+        }
+        
+        ThreadPlanShouldStopHereCallback should_stop_here_callback;
+        ThreadPlanStepFromHereCallback   step_from_here_callback;
+    };
+    
     enum
     {
         eNone = 0,
-        eAvoidInlines = (1 << 0),
-        eAvoidNoDebug = (1 << 1)
+        eAvoidInlines            = (1 << 0),
+        eStepInAvoidNoDebug      = (1 << 1),
+        eStepOutAvoidNoDebug     = (1 << 2)
     };
 
     //------------------------------------------------------------------
     // Constructors and Destructors
     //------------------------------------------------------------------
+    ThreadPlanShouldStopHere (ThreadPlan *owner);
+    
     ThreadPlanShouldStopHere (ThreadPlan *owner,
-                              ThreadPlanShouldStopHereCallback callback = NULL,
+                              const ThreadPlanShouldStopHereCallbacks *callbacks,
                               void *baton = NULL);
     virtual
     ~ThreadPlanShouldStopHere();
-
+    
+    // Set the ShouldStopHere callbacks.  Pass in null to clear them and have no special behavior (though you
+    // can also call ClearShouldStopHereCallbacks for that purpose.  If you pass in a valid pointer, it will
+    // adopt the non-null fields, and any null fields will be set to the default values.
+    
     void
-    SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton);
+    SetShouldStopHereCallbacks (const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton)
+    {
+        if (callbacks)
+        {
+            m_callbacks = *callbacks;
+            if (!m_callbacks.should_stop_here_callback)
+                m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
+            if (!m_callbacks.step_from_here_callback)
+                m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
+        }
+        else
+        {
+            ClearShouldStopHereCallbacks ();
+        }
+        m_baton = baton;
+    }
+    
+    void
+    ClearShouldStopHereCallbacks()
+    {
+        m_callbacks.Clear();
+    }
 
+    bool
+    InvokeShouldStopHereCallback (lldb::FrameComparison operation);
+    
     lldb::ThreadPlanSP
-    InvokeShouldStopHereCallback ();
+    CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation);
 
     lldb_private::Flags &
     GetFlags ()
@@ -69,13 +127,22 @@ public:
     }
 
 protected:
+    static bool
+    DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
+    
+    static lldb::ThreadPlanSP
+    DefaultStepFromHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
+    
+    virtual lldb::ThreadPlanSP
+    QueueStepOutFromHerePlan (Flags &flags, lldb::FrameComparison operation);
+
     // Implement this, and call it in the plan's constructor to set the default flags.
     virtual void SetFlagsToDefault () = 0;
 
     //------------------------------------------------------------------
     // Classes that inherit from ThreadPlanShouldStopHere can see and modify these
     //------------------------------------------------------------------
-    ThreadPlanShouldStopHereCallback m_callback;
+    ThreadPlanShouldStopHereCallbacks m_callbacks;
     void * m_baton;
     ThreadPlan *m_owner;
     lldb_private::Flags m_flags;

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h Wed Mar 12 21:47:14 2014
@@ -30,13 +30,17 @@ public:
     ThreadPlanStepInRange (Thread &thread,
                            const AddressRange &range,
                            const SymbolContext &addr_context,
-                           lldb::RunMode stop_others);
-
+                           lldb::RunMode stop_others,
+                            LazyBool step_in_avoids_code_without_debug_info,
+                            LazyBool step_out_avoids_code_without_debug_info);
+    
     ThreadPlanStepInRange (Thread &thread,
                            const AddressRange &range,
                            const SymbolContext &addr_context,
                            const char *step_into_function_name,
-                           lldb::RunMode stop_others);
+                           lldb::RunMode stop_others,
+                            LazyBool step_in_avoids_code_without_debug_info,
+                            LazyBool step_out_avoids_code_without_debug_info);
 
     virtual
     ~ThreadPlanStepInRange ();
@@ -54,9 +58,6 @@ public:
         m_step_into_target.SetCString(target);
     }
     
-    static lldb::ThreadPlanSP
-    DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton);
-
     static void
     SetDefaultFlagValue (uint32_t new_value);
     
@@ -64,13 +65,26 @@ public:
     IsVirtualStep();
 
 protected:
+    static bool
+    DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
+
     virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
 
     virtual bool
     DoPlanExplainsStop (Event *event_ptr);
 
     virtual void
-    SetFlagsToDefault ();
+    SetFlagsToDefault ()
+    {
+        GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
+    }
+    
+    void
+    SetCallbacks()
+    {
+        ThreadPlanShouldStopHere::ThreadPlanShouldStopHereCallbacks callbacks(ThreadPlanStepInRange::DefaultShouldStopHereCallback, nullptr);
+        SetShouldStopHereCallbacks (&callbacks, nullptr);
+    }
     
     bool
     FrameMatchesAvoidCriteria ();
@@ -81,20 +95,23 @@ private:
     Thread::QueueThreadPlanForStepOverRange (bool abort_other_plans,
                                          const AddressRange &range,
                                          const SymbolContext &addr_context,
-                                         lldb::RunMode stop_others);
+                                         lldb::RunMode stop_others,
+                                         LazyBool avoid_code_without_debug_info);
     friend lldb::ThreadPlanSP
     Thread::QueueThreadPlanForStepInRange (bool abort_other_plans,
                                          const AddressRange &range,
                                          const SymbolContext &addr_context,
                                          const char *step_in_target,
                                          lldb::RunMode stop_others,
-                                         bool avoid_code_without_debug_info);
-
+                                         LazyBool step_in_avoids_code_without_debug_info,
+                                         LazyBool step_out_avoids_code_without_debug_info);
 
+    void SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info,
+                           LazyBool step_out_avoids_code_without_debug_info);
     // Need an appropriate marker for the current stack so we can tell step out
     // from step in.
 
-    static uint32_t s_default_flag_values;
+    static uint32_t s_default_flag_values;  // These are the default flag values for the ThreadPlanStepThrough.
     lldb::ThreadPlanSP m_sub_plan_sp;  // Keep track of the last plan we were running.  If it fails, we should stop.
     std::unique_ptr<RegularExpression> m_avoid_regexp_ap;
     bool m_step_past_prologue;  // FIXME: For now hard-coded to true, we could put a switch in for this if there's

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h Wed Mar 12 21:47:14 2014
@@ -16,10 +16,12 @@
 // Project includes
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanShouldStopHere.h"
 
 namespace lldb_private {
 
-class ThreadPlanStepOut : public ThreadPlan
+class ThreadPlanStepOut : public ThreadPlan,
+                          public ThreadPlanShouldStopHere
 {
 public:
     ThreadPlanStepOut (Thread &thread,
@@ -28,7 +30,8 @@ public:
                        bool stop_others,
                        Vote stop_vote,
                        Vote run_vote,
-                       uint32_t frame_idx);
+                       uint32_t frame_idx,
+                       LazyBool step_out_avoids_code_without_debug_info);
 
     virtual ~ThreadPlanStepOut ();
 
@@ -48,21 +51,29 @@ public:
     }
 
 protected:
+    virtual void
+    SetFlagsToDefault ()
+    {
+        GetFlags().Set(ThreadPlanStepOut::s_default_flag_values);
+    }
+    
     virtual bool DoPlanExplainsStop (Event *event_ptr);
     virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
     bool QueueInlinedStepPlan (bool queue_now);
 
 private:
-    SymbolContext *m_step_from_context;
+    static uint32_t s_default_flag_values;  // These are the default flag values for the ThreadPlanStepThrough.
+    
     lldb::addr_t m_step_from_insn;
     StackID  m_step_out_to_id;
     StackID  m_immediate_step_from_id;
     lldb::break_id_t m_return_bp_id;
     lldb::addr_t m_return_addr;
-    bool m_first_insn;
     bool m_stop_others;
-    lldb::ThreadPlanSP m_step_through_inline_plan_sp;
-    lldb::ThreadPlanSP m_step_out_plan_sp;
+    lldb::ThreadPlanSP m_step_out_to_inline_plan_sp;    // This plan implements step out to the real function containing
+                                                        // an inlined frame so we can then step out of that.
+    lldb::ThreadPlanSP m_step_through_inline_plan_sp;   // This plan then steps past the inlined frame(s).
+    lldb::ThreadPlanSP m_step_out_further_plan_sp;      // This plan keeps stepping out if ShouldStopHere told us to.
     Function *m_immediate_step_from_function;
     lldb::ValueObjectSP m_return_valobj_sp;
 
@@ -73,8 +84,10 @@ private:
                                        bool stop_others,
                                        Vote stop_vote,
                                        Vote run_vote,
-                                       uint32_t frame_idx);
+                                       uint32_t frame_idx,
+                                       LazyBool step_out_avoids_code_without_debug_info);
 
+    void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info);
     // Need an appropriate marker for the current stack so we can tell step out
     // from step in.
 

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h Wed Mar 12 21:47:14 2014
@@ -21,14 +21,16 @@
 
 namespace lldb_private {
 
-class ThreadPlanStepOverRange : public ThreadPlanStepRange
+class ThreadPlanStepOverRange : public ThreadPlanStepRange,
+                                       ThreadPlanShouldStopHere
 {
 public:
 
     ThreadPlanStepOverRange (Thread &thread, 
                              const AddressRange &range, 
                              const SymbolContext &addr_context, 
-                             lldb::RunMode stop_others);
+                             lldb::RunMode stop_others,
+                             LazyBool step_out_avoids_no_debug);
                              
     virtual ~ThreadPlanStepOverRange ();
 
@@ -38,9 +40,20 @@ public:
 protected:
     virtual bool DoPlanExplainsStop (Event *event_ptr);
     virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
-
+    
+    virtual void
+    SetFlagsToDefault ()
+    {
+        GetFlags().Set(ThreadPlanStepOverRange::s_default_flag_values);
+    }
+    
+    
+    
 private:
 
+    static uint32_t s_default_flag_values;
+    
+    void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info);
     bool IsEquivalentContext(const SymbolContext &context);
 
     bool m_first_resume;

Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-interfaces.h (original)
+++ lldb/trunk/include/lldb/lldb-private-interfaces.h Wed Mar 12 21:47:14 2014
@@ -35,7 +35,8 @@ namespace lldb_private
     typedef SymbolVendor* (*SymbolVendorCreateInstance) (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm);   // Module can be NULL for default system symbol vendor
     typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
     typedef bool (*WatchpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id);
-    typedef lldb::ThreadPlanSP (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, void *baton);
+    typedef bool (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
+    typedef lldb::ThreadPlanSP (*ThreadPlanStepFromHereCallback) (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
     typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch);
     typedef int (*ComparisonFunction)(const void *, const void *);
     typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Wed Mar 12 21:47:14 2014
@@ -601,11 +601,13 @@ SBThread::StepOver (lldb::RunMode stop_o
         {
             if (frame_sp->HasDebugInformation ())
             {
+                const LazyBool avoid_no_debug = eLazyBoolCalculate;
                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
                                                                     sc.line_entry.range,
                                                                     sc,
-                                                                    stop_other_threads);
+                                                                    stop_other_threads,
+                                                                    avoid_no_debug);
             }
             else
             {
@@ -650,14 +652,16 @@ SBThread::StepInto (const char *target_n
 
         if (frame_sp && frame_sp->HasDebugInformation ())
         {
-            bool avoid_code_without_debug_info = true;
+            const LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate;
+            const LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate;
             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
             new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
                                                               sc.line_entry.range,
                                                               sc,
                                                               target_name,
                                                               stop_other_threads,
-                                                              avoid_code_without_debug_info);
+                                                              step_in_avoids_code_without_debug_info,
+                                                              step_out_avoids_code_without_debug_info);
         }
         else
         {
@@ -690,13 +694,15 @@ SBThread::StepOut ()
 
         Thread *thread = exe_ctx.GetThreadPtr();
 
+        const LazyBool avoid_no_debug = eLazyBoolCalculate;
         ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
                                                                   NULL, 
                                                                   false, 
                                                                   stop_other_threads, 
                                                                   eVoteYes, 
                                                                   eVoteNoOpinion,
-                                                                  0));
+                                                                  0,
+                                                                  avoid_no_debug));
                                                                   
         // This returns an error, we should use it!
         ResumeNewPlan (exe_ctx, new_plan_sp.get());

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Wed Mar 12 21:47:14 2014
@@ -348,9 +348,26 @@ public:
             case 'a':
                 {
                     bool success;
-                    m_avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
+                    bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
                     if (!success)
                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
+                    else
+                    {
+                        m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+                    }
+                }
+                break;
+            
+            case 'A':
+                {
+                    bool success;
+                    bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
+                    else
+                    {
+                        m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
+                    }
                 }
                 break;
             
@@ -386,7 +403,8 @@ public:
         void
         OptionParsingStarting ()
         {
-            m_avoid_no_debug = true;
+            m_step_in_avoid_no_debug = eLazyBoolCalculate;
+            m_step_out_avoid_no_debug = eLazyBoolCalculate;
             m_run_mode = eOnlyDuringStepping;
             m_avoid_regexp.clear();
             m_step_in_target.clear();
@@ -403,7 +421,8 @@ public:
         static OptionDefinition g_option_table[];
 
         // Instance variables to hold the values for command options.
-        bool m_avoid_no_debug;
+        LazyBool m_step_in_avoid_no_debug;
+        LazyBool m_step_out_avoid_no_debug;
         RunMode m_run_mode;
         std::string m_avoid_regexp;
         std::string m_step_in_target;
@@ -522,7 +541,9 @@ protected:
                                                                 frame->GetSymbolContext(eSymbolContextEverything),
                                                                 m_options.m_step_in_target.c_str(),
                                                                 stop_other_threads,
-                                                                m_options.m_avoid_no_debug);
+                                                                m_options.m_step_in_avoid_no_debug,
+                                                                m_options.m_step_out_avoid_no_debug);
+                
                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
                 {
                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
@@ -541,7 +562,8 @@ protected:
                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
                                                                     frame->GetSymbolContext(eSymbolContextEverything), 
-                                                                    stop_other_threads);
+                                                                    stop_other_threads,
+                                                                    m_options.m_step_out_avoid_no_debug);
             else
                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
                                                                             abort_other_plans, 
@@ -564,7 +586,8 @@ protected:
                                                           bool_stop_other_threads, 
                                                           eVoteYes, 
                                                           eVoteNoOpinion, 
-                                                          thread->GetSelectedFrameIndex());
+                                                          thread->GetSelectedFrameIndex(),
+                                                          m_options.m_step_out_avoid_no_debug);
         }
         else
         {
@@ -639,7 +662,8 @@ g_duo_running_mode[] =
 OptionDefinition
 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
 {
-{ LLDB_OPT_SET_1, false, "avoid-no-debug",  'a', OptionParser::eRequiredArgument, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether step-in will step over functions with no debug information."},
+{ LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, 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,               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, "run-mode",        'm', OptionParser::eRequiredArgument, 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,               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,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},

Modified: lldb/trunk/source/Core/IOHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/IOHandler.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Core/IOHandler.cpp (original)
+++ lldb/trunk/source/Core/IOHandler.cpp Wed Mar 12 21:47:14 2014
@@ -4092,7 +4092,7 @@ public:
                     {
                         Process *process = exe_ctx.GetProcessPtr();
                         if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
-                            exe_ctx.GetThreadRef().StepIn(true, true);
+                            exe_ctx.GetThreadRef().StepIn(true);
                     }
                 }
                 return MenuActionResult::Handled;
@@ -5117,8 +5117,7 @@ public:
                     if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
                     {
                         bool source_step = (c == 's');
-                        bool avoid_code_without_debug_info = true;
-                        exe_ctx.GetThreadRef().StepIn(source_step, avoid_code_without_debug_info);
+                        exe_ctx.GetThreadRef().StepIn(source_step);
                     }
                 }
                 return eKeyHandled;

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=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Wed Mar 12 21:47:14 2014
@@ -187,14 +187,16 @@ AppleThreadPlanStepThroughObjCTrampoline
                 log->Printf ("Implementation lookup returned msgForward function: 0x%" PRIx64 ", stopping.", target_addr);
 
             SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(eSymbolContextEverything);
-            m_run_to_sp.reset(new ThreadPlanStepOut (m_thread, 
-                                                     &sc, 
-                                                     true, 
-                                                     m_stop_others, 
-                                                     eVoteNoOpinion, 
-                                                     eVoteNoOpinion,
-                                                     0));
-            m_thread.QueueThreadPlan(m_run_to_sp, false);
+            const bool abort_other_plans = false;
+            const bool first_insn = true;
+            const uint32_t frame_idx = 0;
+            m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (abort_other_plans,
+                                           &sc,
+                                           first_insn,
+                                           m_stop_others,
+                                           eVoteNoOpinion,
+                                           eVoteNoOpinion,
+                                           frame_idx);
             m_run_to_sp->SetPrivate(true);
             return false;
         }

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Wed Mar 12 21:47:14 2014
@@ -61,6 +61,9 @@ Thread::GetGlobalProperties()
 static PropertyDefinition
 g_properties[] =
 {
+    { "step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, step-in will not stop in functions with no debug information." },
+    { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with "
+                                                                                    "debug information.  Passing a frame argument to step-out will override this option." },
     { "step-avoid-regexp",  OptionValue::eTypeRegex  , true , REG_EXTENDED, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
     { "step-avoid-libraries",  OptionValue::eTypeFileSpecList  , true , REG_EXTENDED, NULL, NULL, "A list of libraries that source stepping won't stop in." },
     { "trace-thread",       OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." },
@@ -68,6 +71,8 @@ g_properties[] =
 };
 
 enum {
+    ePropertyStepInAvoidsNoDebug,
+    ePropertyStepOutAvoidsNoDebug,
     ePropertyStepAvoidRegex,
     ePropertyStepAvoidLibraries,
     ePropertyEnableThreadTrace
@@ -151,6 +156,21 @@ ThreadProperties::GetTraceEnabledState()
     return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
 }
 
+bool
+ThreadProperties::GetStepInAvoidsNoDebug() const
+{
+    const uint32_t idx = ePropertyStepInAvoidsNoDebug;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
+ThreadProperties::GetStepOutAvoidsNoDebug() const
+{
+    const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+
 //------------------------------------------------------------------
 // Thread Event Data
 //------------------------------------------------------------------
@@ -1425,12 +1445,13 @@ Thread::QueueThreadPlanForStepOverRange
     bool abort_other_plans, 
     const AddressRange &range, 
     const SymbolContext &addr_context,
-    lldb::RunMode stop_other_threads
+    lldb::RunMode stop_other_threads,
+    LazyBool step_out_avoids_code_withoug_debug_info
 )
 {
     ThreadPlanSP thread_plan_sp;
-    thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
-
+    thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads, step_out_avoids_code_withoug_debug_info));
+    
     QueueThreadPlan (thread_plan_sp, abort_other_plans);
     return thread_plan_sp;
 }
@@ -1443,17 +1464,21 @@ Thread::QueueThreadPlanForStepInRange
     const SymbolContext &addr_context,
     const char *step_in_target,
     lldb::RunMode stop_other_threads,
-    bool avoid_code_without_debug_info
+    LazyBool step_in_avoids_code_without_debug_info,
+    LazyBool step_out_avoids_code_without_debug_info
 )
 {
     ThreadPlanSP thread_plan_sp;
-    ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
-    if (avoid_code_without_debug_info)
-        plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
-    else
-        plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+    ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this,
+                                                             range,
+                                                             addr_context,
+                                                             stop_other_threads,
+                                                             step_in_avoids_code_without_debug_info,
+                                                             step_out_avoids_code_without_debug_info);
+    
     if (step_in_target)
         plan->SetStepInTarget(step_in_target);
+    
     thread_plan_sp.reset (plan);
 
     QueueThreadPlan (thread_plan_sp, abort_other_plans);
@@ -1470,7 +1495,8 @@ Thread::QueueThreadPlanForStepOut
     bool stop_other_threads, 
     Vote stop_vote, 
     Vote run_vote,
-    uint32_t frame_idx
+    uint32_t frame_idx,
+    LazyBool step_out_avoids_code_withoug_debug_info
 )
 {
     ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this, 
@@ -1479,7 +1505,42 @@ Thread::QueueThreadPlanForStepOut
                                                         stop_other_threads, 
                                                         stop_vote, 
                                                         run_vote, 
-                                                        frame_idx));
+                                                        frame_idx,
+                                                        step_out_avoids_code_withoug_debug_info));
+    
+    if (thread_plan_sp->ValidatePlan(NULL))
+    {
+        QueueThreadPlan (thread_plan_sp, abort_other_plans);
+        return thread_plan_sp;
+    }
+    else
+    {
+        return ThreadPlanSP();
+    }
+}
+
+ThreadPlanSP
+Thread::QueueThreadPlanForStepOutNoShouldStop
+(
+    bool abort_other_plans, 
+    SymbolContext *addr_context, 
+    bool first_insn,
+    bool stop_other_threads, 
+    Vote stop_vote, 
+    Vote run_vote,
+    uint32_t frame_idx
+)
+{
+    ThreadPlanStepOut *new_plan = new ThreadPlanStepOut (*this,
+                                                        addr_context, 
+                                                        first_insn, 
+                                                        stop_other_threads, 
+                                                        stop_vote, 
+                                                        run_vote, 
+                                                        frame_idx,
+                                                        eLazyBoolNo);
+    new_plan->ClearShouldStopHereCallbacks();
+    ThreadPlanSP thread_plan_sp(new_plan);
     
     if (thread_plan_sp->ValidatePlan(NULL))
     {
@@ -2070,8 +2131,9 @@ Thread::IsStillAtLastBreakpointHit ()
 
 Error
 Thread::StepIn (bool source_step,
-                bool avoid_code_without_debug_info)
-               
+                LazyBool step_in_avoids_code_without_debug_info,
+                LazyBool step_out_avoids_code_without_debug_info)
+
 {
     Error error;
     Process *process = GetProcess().get();
@@ -2090,7 +2152,8 @@ Thread::StepIn (bool source_step,
                                                          sc,
                                                          NULL,
                                                          run_mode,
-                                                         avoid_code_without_debug_info);
+                                                         step_in_avoids_code_without_debug_info,
+                                                         step_out_avoids_code_without_debug_info);
         }
         else
         {
@@ -2114,8 +2177,8 @@ Thread::StepIn (bool source_step,
 }
 
 Error
-Thread::StepOver (bool source_step)
-
+Thread::StepOver (bool source_step,
+                LazyBool step_out_avoids_code_without_debug_info)
 {
     Error error;
     Process *process = GetProcess().get();
@@ -2133,7 +2196,8 @@ Thread::StepOver (bool source_step)
             new_plan_sp = QueueThreadPlanForStepOverRange (abort_other_plans,
                                                            sc.line_entry.range,
                                                            sc,
-                                                           run_mode);
+                                                           run_mode,
+                                                           step_out_avoids_code_without_debug_info);
         }
         else
         {
@@ -2187,4 +2251,4 @@ Thread::StepOut ()
         error.SetErrorString("process not stopped");
     }
     return error;
-}
\ No newline at end of file
+}

Modified: lldb/trunk/source/Target/ThreadPlanShouldStopHere.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanShouldStopHere.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanShouldStopHere.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanShouldStopHere.cpp Wed Mar 12 21:47:14 2014
@@ -23,12 +23,23 @@ using namespace lldb_private;
 //----------------------------------------------------------------------
 // ThreadPlanShouldStopHere constructor
 //----------------------------------------------------------------------
-ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, ThreadPlanShouldStopHereCallback callback, void *baton) :
-    m_callback (callback),
-    m_baton (baton),
+ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner) :
+    m_callbacks (),
+    m_baton (NULL),
     m_owner (owner),
     m_flags (ThreadPlanShouldStopHere::eNone)
 {
+    m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
+    m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
+}
+
+ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton) :
+    m_callbacks (),
+    m_baton (),
+    m_owner (owner),
+    m_flags (ThreadPlanShouldStopHere::eNone)
+{
+    SetShouldStopHereCallbacks(callbacks, baton);
 }
 
 //----------------------------------------------------------------------
@@ -38,37 +49,86 @@ ThreadPlanShouldStopHere::~ThreadPlanSho
 {
 }
 
-void
-ThreadPlanShouldStopHere::SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton)
-{
-    m_callback = callback;
-    m_baton = baton;
-}
-
-ThreadPlanSP
-ThreadPlanShouldStopHere::InvokeShouldStopHereCallback ()
+bool
+ThreadPlanShouldStopHere::InvokeShouldStopHereCallback (FrameComparison operation)
 {
-    if (m_callback)
+    bool should_stop_here = true;
+    if (m_callbacks.should_stop_here_callback)
     {
-        ThreadPlanSP return_plan_sp(m_callback (m_owner, m_flags, m_baton));
+        should_stop_here = m_callbacks.should_stop_here_callback (m_owner, m_flags, operation, m_baton);
         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
         if (log)
         {
             lldb::addr_t current_addr = m_owner->GetThread().GetRegisterContext()->GetPC(0);
 
-            if (return_plan_sp)
-            {
-                StreamString s;
-                return_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
-                log->Printf ("ShouldStopHere callback found a step out plan from 0x%" PRIx64 ": %s.", current_addr, s.GetData());
-            }
-            else
-            {
-                log->Printf ("ShouldStopHere callback didn't find a step out plan from: 0x%" PRIx64 ".", current_addr);
-            }
+            log->Printf ("ShouldStopHere callback returned %u from 0x%" PRIx64 ".", should_stop_here, current_addr);
         }
+    }
+    
+    return should_stop_here;
+}
+
+bool
+ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
+                                                         Flags &flags,
+                                                         FrameComparison operation,
+                                                         void *baton)
+{
+    bool should_stop_here = true;
+    StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+    if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug))
+        || (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug)))
+    {
+        if (!frame->HasDebugInformation())
+        {
+            if (log)
+                log->Printf ("Stepping out of frame with no debug info");
+
+            should_stop_here = false;
+        }
+    }
+    
+    return should_stop_here;
+}
+
+ThreadPlanSP
+ThreadPlanShouldStopHere::DefaultStepFromHereCallback (ThreadPlan *current_plan,
+                                                         Flags &flags,
+                                                         FrameComparison operation,
+                                                         void *baton)
+{
+        const bool stop_others = false;
+        const size_t frame_index = 0;
+        ThreadPlanSP return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop (false,
+                                                                                                  NULL,
+                                                                                                  true,
+                                                                                                  stop_others,
+                                                                                                  eVoteNo,
+                                                                                                  eVoteNoOpinion,
+                                                                                                  frame_index);
         return return_plan_sp;
+}
+
+ThreadPlanSP
+ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(lldb_private::Flags &flags, lldb::FrameComparison operation)
+{
+    ThreadPlanSP return_plan_sp;
+    if (m_callbacks.step_from_here_callback)
+    {
+         return_plan_sp = m_callbacks.step_from_here_callback (m_owner, flags, operation, m_baton);
     }
+    return return_plan_sp;
+
+}
+
+lldb::ThreadPlanSP
+ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation)
+{
+    if (!InvokeShouldStopHereCallback(operation))
+        return QueueStepOutFromHerePlan(m_flags, operation);
     else
         return ThreadPlanSP();
 }
+

Modified: lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInRange.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInRange.cpp Wed Mar 12 21:47:14 2014
@@ -31,7 +31,7 @@
 using namespace lldb;
 using namespace lldb_private;
 
-uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
+uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eStepInAvoidNoDebug;
 
 //----------------------------------------------------------------------
 // ThreadPlanStepInRange: Step through a stack range, either stepping over or into
@@ -43,14 +43,18 @@ ThreadPlanStepInRange::ThreadPlanStepInR
     Thread &thread,
     const AddressRange &range,
     const SymbolContext &addr_context,
-    lldb::RunMode stop_others
+    lldb::RunMode stop_others,
+    LazyBool step_in_avoids_code_without_debug_info,
+    LazyBool step_out_avoids_code_without_debug_info
 ) :
     ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
-    ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+    ThreadPlanShouldStopHere (this),
     m_step_past_prologue (true),
     m_virtual_step (false)
 {
+    SetCallbacks();
     SetFlagsToDefault ();
+    SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
 }
 
 ThreadPlanStepInRange::ThreadPlanStepInRange
@@ -59,15 +63,19 @@ ThreadPlanStepInRange::ThreadPlanStepInR
     const AddressRange &range,
     const SymbolContext &addr_context,
     const char *step_into_target,
-    lldb::RunMode stop_others
+    lldb::RunMode stop_others,
+    LazyBool step_in_avoids_code_without_debug_info,
+    LazyBool step_out_avoids_code_without_debug_info
 ) :
     ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
-    ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+    ThreadPlanShouldStopHere (this),
     m_step_past_prologue (true),
     m_virtual_step (false),
     m_step_into_target (step_into_target)
 {
+    SetCallbacks();
     SetFlagsToDefault ();
+    SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
 }
 
 ThreadPlanStepInRange::~ThreadPlanStepInRange ()
@@ -75,6 +83,48 @@ ThreadPlanStepInRange::~ThreadPlanStepIn
 }
 
 void
+ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info,
+                                         LazyBool step_out_avoids_code_without_debug_info)
+{
+    bool avoid_nodebug = true;
+    
+    switch (step_in_avoids_code_without_debug_info)
+    {
+        case eLazyBoolYes:
+            avoid_nodebug = true;
+            break;
+        case eLazyBoolNo:
+            avoid_nodebug = false;
+            break;
+        case eLazyBoolCalculate:
+            avoid_nodebug = m_thread.GetStepInAvoidsNoDebug();
+            break;
+    }
+    if (avoid_nodebug)
+        GetFlags().Set (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+    else
+        GetFlags().Clear (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+    
+    avoid_nodebug = true;
+    switch (step_out_avoids_code_without_debug_info)
+    {
+        case eLazyBoolYes:
+            avoid_nodebug = true;
+            break;
+        case eLazyBoolNo:
+            avoid_nodebug = false;
+            break;
+        case eLazyBoolCalculate:
+            avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+            break;
+    }
+    if (avoid_nodebug)
+        GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+    else
+        GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+}
+
+void
 ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
     if (level == lldb::eDescriptionLevelBrief)
@@ -124,7 +174,8 @@ ThreadPlanStepInRange::ShouldStop (Event
     {
         // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
         // we're done.
-        m_sub_plan_sp = InvokeShouldStopHereCallback();
+        // FIXME - This can be both a step in and a step out.  Probably should record which in the m_virtual_step.
+        m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
     }
     else
     {
@@ -148,7 +199,12 @@ ThreadPlanStepInRange::ShouldStop (Event
             // in a trampoline we think the frame is older because the trampoline confused the backtracer.
             m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
             if (!m_sub_plan_sp)
-                return true;
+            {
+                // Otherwise check the ShouldStopHere for step out:
+                m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareOlder);
+                if (log)
+                    log->Printf ("ShouldStopHere says we should step out of this frame.");
+            }
             else if (log)
             {
                 log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
@@ -196,7 +252,7 @@ ThreadPlanStepInRange::ShouldStop (Event
         // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
         // But only do that if we actually have stepped in.
         if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
-            m_sub_plan_sp = InvokeShouldStopHereCallback();
+            m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
 
         // If we've stepped in and we are going to stop here, check to see if we were asked to
         // run past the prologue, and if so do that.
@@ -251,12 +307,6 @@ ThreadPlanStepInRange::ShouldStop (Event
     }
 }
 
-void
-ThreadPlanStepInRange::SetFlagsToDefault ()
-{
-    GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
-}
-
 void 
 ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
 {
@@ -344,25 +394,26 @@ ThreadPlanStepInRange::FrameMatchesAvoid
     return false;
 }
 
-ThreadPlanSP
-ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
+bool
+ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, FrameComparison operation, void *baton)
 {
-    bool should_step_out = false;
+    bool should_stop_here = true;
     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
 
-    if (flags.Test(eAvoidNoDebug))
+    if ((operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug))
+        || (operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug)))
     {
         if (!frame->HasDebugInformation())
         {
             if (log)
                 log->Printf ("Stepping out of frame with no debug info");
 
-            should_step_out = true;
+            should_stop_here = false;
         }
     }
     
-    if (current_plan->GetKind() == eKindStepInRange)
+    if (should_stop_here && current_plan->GetKind() == eKindStepInRange && operation == eFrameCompareYounger)
     {
         ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
         if (step_in_range_plan->m_step_into_target)
@@ -373,7 +424,7 @@ ThreadPlanStepInRange::DefaultShouldStop
                 // First try an exact match, since that's cheap with ConstStrings.  Then do a strstr compare.
                 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
                 {
-                    should_step_out = false;
+                    should_stop_here = true;
                 }
                 else
                 {
@@ -381,42 +432,26 @@ ThreadPlanStepInRange::DefaultShouldStop
                     const char *function_name = sc.GetFunctionName().AsCString();
                     
                     if (function_name == NULL)
-                        should_step_out = true;
+                        should_stop_here = false;
                     else if (strstr (function_name, target_name) == NULL)
-                        should_step_out = true;
+                        should_stop_here = false;
                 }
-                if (log && should_step_out)
+                if (log && !should_stop_here)
                     log->Printf("Stepping out of frame %s which did not match step into target %s.",
                                 sc.GetFunctionName().AsCString(),
                                 step_in_range_plan->m_step_into_target.AsCString());
             }
         }
         
-        if (!should_step_out)
+        if (should_stop_here)
         {
             ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
             // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria.
-            should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria ();
+            should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria ();
         }
     }
     
-    
-    if (should_step_out)
-    {
-        // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
-        // We really should have all plans take the tri-state for "stop others" so we can do the right
-        // thing.  For now let's be safe and always run others when we are likely to run arbitrary code.
-        const bool stop_others = false;
-        return current_plan->GetThread().QueueThreadPlanForStepOut (false, 
-                                                                    NULL, 
-                                                                    true, 
-                                                                    stop_others,
-                                                                    eVoteNo, 
-                                                                    eVoteNoOpinion,
-                                                                    0); // Frame index
-    }
-
-    return ThreadPlanSP();
+    return should_stop_here;
 }
 
 bool

Modified: lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp Wed Mar 12 21:47:14 2014
@@ -147,13 +147,13 @@ ThreadPlanStepInstruction::ShouldStop (E
                     // StepInstruction should probably have the tri-state RunMode, but for now it is safer to
                     // run others.
                     const bool stop_others = false;
-                    m_thread.QueueThreadPlanForStepOut(false,
-                                                       NULL,
-                                                       true,
-                                                       stop_others,
-                                                       eVoteNo,
-                                                       eVoteNoOpinion,
-                                                       0);
+                    m_thread.QueueThreadPlanForStepOutNoShouldStop(false,
+                                                                   NULL,
+                                                                   true,
+                                                                   stop_others,
+                                                                   eVoteNo,
+                                                                   eVoteNoOpinion,
+                                                                   0);
                     return false;
                 }
                 else

Modified: lldb/trunk/source/Target/ThreadPlanStepOut.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOut.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepOut.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepOut.cpp Wed Mar 12 21:47:14 2014
@@ -26,10 +26,13 @@
 #include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/ThreadPlanStepOverRange.h"
+#include "lldb/Target/ThreadPlanStepThrough.h"
 
 using namespace lldb;
 using namespace lldb_private;
 
+uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
+
 //----------------------------------------------------------------------
 // ThreadPlanStepOut: Step out of the current frame
 //----------------------------------------------------------------------
@@ -41,20 +44,21 @@ ThreadPlanStepOut::ThreadPlanStepOut
     bool stop_others,
     Vote stop_vote,
     Vote run_vote,
-    uint32_t frame_idx
+    uint32_t frame_idx,
+    LazyBool step_out_avoids_code_without_debug_info
 ) :
     ThreadPlan (ThreadPlan::eKindStepOut, "Step out", thread, stop_vote, run_vote),
-    m_step_from_context (context),
+    ThreadPlanShouldStopHere (this),
     m_step_from_insn (LLDB_INVALID_ADDRESS),
     m_return_bp_id (LLDB_INVALID_BREAK_ID),
     m_return_addr (LLDB_INVALID_ADDRESS),
-    m_first_insn (first_insn),
     m_stop_others (stop_others),
-    m_step_through_inline_plan_sp(),
-    m_step_out_plan_sp (),
     m_immediate_step_from_function(NULL)
 
 {
+    SetFlagsToDefault();
+    SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
+    
     m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
 
     StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1));
@@ -77,13 +81,15 @@ ThreadPlanStepOut::ThreadPlanStepOut
         {
             // First queue a plan that gets us to this inlined frame, and when we get there we'll queue a second
             // plan that walks us out of this frame.
-            m_step_out_plan_sp.reset (new ThreadPlanStepOut(m_thread, 
+            m_step_out_to_inline_plan_sp.reset (new ThreadPlanStepOut(m_thread,
                                                             NULL, 
                                                             false,
                                                             stop_others, 
                                                             eVoteNoOpinion, 
                                                             eVoteNoOpinion, 
-                                                            frame_idx - 1));
+                                                            frame_idx - 1,
+                                                            eLazyBoolNo));
+            static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
         }
         else
         {
@@ -123,10 +129,32 @@ ThreadPlanStepOut::ThreadPlanStepOut
 }
 
 void
+ThreadPlanStepOut::SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info)
+{
+    bool avoid_nodebug = true;
+    switch (step_out_avoids_code_without_debug_info)
+    {
+        case eLazyBoolYes:
+            avoid_nodebug = true;
+            break;
+        case eLazyBoolNo:
+            avoid_nodebug = false;
+            break;
+        case eLazyBoolCalculate:
+            avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+            break;
+    }
+    if (avoid_nodebug)
+        GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+    else
+        GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+}
+
+void
 ThreadPlanStepOut::DidPush()
 {
-    if (m_step_out_plan_sp)
-        m_thread.QueueThreadPlan(m_step_out_plan_sp, false);
+    if (m_step_out_to_inline_plan_sp)
+        m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
     else if (m_step_through_inline_plan_sp)
         m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
 }
@@ -144,7 +172,7 @@ ThreadPlanStepOut::GetDescription (Strea
         s->Printf ("step out");
     else
     {
-        if (m_step_out_plan_sp)
+        if (m_step_out_to_inline_plan_sp)
             s->Printf ("Stepping out to inlined frame so we can walk through it.");
         else if (m_step_through_inline_plan_sp)
             s->Printf ("Stepping out by stepping through inlined function.");
@@ -159,8 +187,8 @@ ThreadPlanStepOut::GetDescription (Strea
 bool
 ThreadPlanStepOut::ValidatePlan (Stream *error)
 {
-    if (m_step_out_plan_sp)
-        return m_step_out_plan_sp->ValidatePlan (error);
+    if (m_step_out_to_inline_plan_sp)
+        return m_step_out_to_inline_plan_sp->ValidatePlan (error);
     else if (m_step_through_inline_plan_sp)
         return m_step_through_inline_plan_sp->ValidatePlan (error);
     else if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
@@ -176,12 +204,18 @@ ThreadPlanStepOut::ValidatePlan (Stream
 bool
 ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
 {
-    // If one of our child plans just finished, then we do explain the stop.
-    if (m_step_out_plan_sp)
+    // If the step out plan is done, then we just need to step through the inlined frame.
+    if (m_step_out_to_inline_plan_sp)
     {
-        if (m_step_out_plan_sp->MischiefManaged())
+        if (m_step_out_to_inline_plan_sp->MischiefManaged())
+            return true;
+        else
+            return false;
+    }
+    else if (m_step_through_inline_plan_sp)
+    {
+        if (m_step_through_inline_plan_sp->MischiefManaged())
         {
-            // If this one is done, then we are all done.
             CalculateReturnValue();
             SetPlanComplete();
             return true;
@@ -189,9 +223,9 @@ ThreadPlanStepOut::DoPlanExplainsStop (E
         else
             return false;
     }
-    else if (m_step_through_inline_plan_sp)
+    else if (m_step_out_further_plan_sp)
     {
-        if (m_step_through_inline_plan_sp->MischiefManaged())
+        if (m_step_out_further_plan_sp->MischiefManaged())
             return true;
         else
             return false;
@@ -234,8 +268,11 @@ ThreadPlanStepOut::DoPlanExplainsStop (E
                     
                 if (done)
                 {
-                    CalculateReturnValue();
-                    SetPlanComplete();
+                    if (InvokeShouldStopHereCallback (eFrameCompareOlder))
+                    {
+                        CalculateReturnValue();
+                        SetPlanComplete();
+                    }
                 }
 
                 // If there was only one owner, then we're done.  But if we also hit some
@@ -266,61 +303,70 @@ ThreadPlanStepOut::DoPlanExplainsStop (E
 bool
 ThreadPlanStepOut::ShouldStop (Event *event_ptr)
 {
-        if (IsPlanComplete())
-            return true;
-        
-        bool done;
-        
+    if (IsPlanComplete())
+        return true;
+    
+    bool done = false;
+    if (m_step_out_to_inline_plan_sp)
+    {
+        if (m_step_out_to_inline_plan_sp->MischiefManaged())
+        {
+            // Now step through the inlined stack we are in:
+            if (QueueInlinedStepPlan(true))
+            {
+                // If we can't queue a plan to do this, then just call ourselves done.
+                m_step_out_to_inline_plan_sp.reset();
+                SetPlanComplete (false);
+                return true;
+            }
+            else
+                done = true;
+        }
+        else
+            return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
+    }
+    else if (m_step_through_inline_plan_sp)
+    {
+        if (m_step_through_inline_plan_sp->MischiefManaged())
+            done = true;
+        else
+            return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
+    }
+    else if (m_step_out_further_plan_sp)
+    {
+        if (m_step_out_further_plan_sp->MischiefManaged())
+            m_step_out_further_plan_sp.reset();
+        else
+            return m_step_out_further_plan_sp->ShouldStop(event_ptr);
+    }
+
+    if (!done)
+    {
         StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
         if (frame_zero_id < m_step_out_to_id)
             done = false;
         else
             done = true;
-            
-        if (done)
+    }
+
+    // The normal step out computations think we are done, so all we need to do is consult the ShouldStopHere,
+    // and we are done.
+    
+    if (done)
+    {
+        if (InvokeShouldStopHereCallback(eFrameCompareOlder))
         {
             CalculateReturnValue();
             SetPlanComplete();
-            return true;
         }
         else
         {
-            if (m_step_out_plan_sp)
-            {
-                if (m_step_out_plan_sp->MischiefManaged())
-                {
-                    // Now step through the inlined stack we are in:
-                    if (QueueInlinedStepPlan(true))
-                    {
-                        return false;
-                    }
-                    else
-                    {
-                        CalculateReturnValue();
-                        SetPlanComplete ();
-                        return true;
-                    }
-                }
-                else
-                    return m_step_out_plan_sp->ShouldStop(event_ptr);
-            }
-            else if (m_step_through_inline_plan_sp)
-            {
-                if (m_step_through_inline_plan_sp->MischiefManaged())
-                {
-                    // We don't calculate the return value here because we don't know how to.
-                    // But in case we had a return value sitting around from our process in
-                    // getting here, let's clear it out.
-                    m_return_valobj_sp.reset();
-                    SetPlanComplete();
-                    return true;
-                }
-                else
-                    return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
-            }
-            else
-                return false;
+            m_step_out_further_plan_sp = QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
+            done = false;
         }
+    }
+
+    return done;
 }
 
 bool
@@ -338,7 +384,7 @@ ThreadPlanStepOut::GetPlanRunState ()
 bool
 ThreadPlanStepOut::DoWillResume (StateType resume_state, bool current_plan)
 {
-    if (m_step_out_plan_sp || m_step_through_inline_plan_sp)
+    if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
         return true;
         
     if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
@@ -427,10 +473,12 @@ ThreadPlanStepOut::QueueInlinedStepPlan
                 inlined_block->CalculateSymbolContext(&inlined_sc);
                 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);
+                                                                                                    run_mode,
+                                                                                                    avoid_no_debug);
                 step_through_inline_plan_ptr->SetOkayToDiscard(true);                                                                                    
                 StreamString errors;
                 if (!step_through_inline_plan_ptr->ValidatePlan(&errors))
@@ -486,4 +534,3 @@ ThreadPlanStepOut::IsPlanStale()
     else
         return true;
 }
-

Modified: lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp Wed Mar 12 21:47:14 2014
@@ -31,6 +31,7 @@
 using namespace lldb_private;
 using namespace lldb;
 
+uint32_t ThreadPlanStepOverRange::s_default_flag_values = 0;
 
 //----------------------------------------------------------------------
 // ThreadPlanStepOverRange: Step through a stack range, either stepping over or into
@@ -42,11 +43,15 @@ ThreadPlanStepOverRange::ThreadPlanStepO
     Thread &thread,
     const AddressRange &range,
     const SymbolContext &addr_context,
-    lldb::RunMode stop_others
+    lldb::RunMode stop_others,
+    LazyBool step_out_avoids_code_without_debug_info
 ) :
     ThreadPlanStepRange (ThreadPlan::eKindStepOverRange, "Step range stepping over", thread, range, addr_context, stop_others),
+    ThreadPlanShouldStopHere (this),
     m_first_resume(true)
 {
+    SetFlagsToDefault();
+    SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
 }
 
 ThreadPlanStepOverRange::~ThreadPlanStepOverRange ()
@@ -65,6 +70,28 @@ ThreadPlanStepOverRange::GetDescription
     }
 }
 
+void
+ThreadPlanStepOverRange::SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info)
+{
+    bool avoid_nodebug = true;
+    switch (step_out_avoids_code_without_debug_info)
+    {
+        case eLazyBoolYes:
+            avoid_nodebug = true;
+            break;
+        case eLazyBoolNo:
+            avoid_nodebug = false;
+            break;
+        case eLazyBoolCalculate:
+            avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+            break;
+    }
+    if (avoid_nodebug)
+        GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+    else
+        GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+}
+
 bool
 ThreadPlanStepOverRange::IsEquivalentContext(const SymbolContext &context)
 {
@@ -146,13 +173,13 @@ ThreadPlanStepOverRange::ShouldStop (Eve
             const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything);
             if (IsEquivalentContext(older_context))
             {
-                new_plan_sp = m_thread.QueueThreadPlanForStepOut (false,
-                                                           NULL,
-                                                           true,
-                                                           stop_others,
-                                                           eVoteNo,
-                                                           eVoteNoOpinion,
-                                                           0);
+                new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (false,
+                                                                              NULL,
+                                                                              true,
+                                                                              stop_others,
+                                                                              eVoteNo,
+                                                                              eVoteNoOpinion,
+                                                                              0);
                 break;
             }
             else
@@ -277,6 +304,13 @@ ThreadPlanStepOverRange::ShouldStop (Eve
     // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it:
     ClearNextBranchBreakpoint();
     
+    
+    // If we haven't figured out something to do yet, then ask the ShouldStopHere callback:
+    if (!new_plan_sp)
+    {
+        new_plan_sp = CheckShouldStopHereAndQueueStepOut (frame_order);
+    }
+    
     if (!new_plan_sp)
         m_no_more_plans = true;
     else
@@ -390,3 +424,4 @@ ThreadPlanStepOverRange::DoWillResume (l
     
     return true;
 }
+

Modified: lldb/trunk/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=203747&r1=203746&r2=203747&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Wed Mar 12 21:47:14 2014
@@ -92,6 +92,9 @@ endif
 CFLAGS ?= -g -O0
 CFLAGS += $(ARCHFLAG)$(ARCH) $(FRAMEWORK_INCLUDES) $(CFLAGS_EXTRAS)
 
+# Use this one if you want to build one part of the result without debug information:
+CFLAGS_NO_DEBUG = -O0 $(ARCHFLAG)$(ARCH) $(FRAMEWORK_INCLUDES) $(CFLAGS_EXTRAS)
+
 CXXFLAGS +=$(CFLAGS)
 LD = $(CC)
 LDFLAGS ?= $(CFLAGS)





More information about the lldb-commits mailing list