[Lldb-commits] [lldb] r156101 - in /lldb/trunk: include/lldb/API/ include/lldb/Target/ lldb.xcodeproj/ source/API/ source/Commands/ source/Target/ tools/debugserver/debugserver.xcodeproj/

Jim Ingham jingham at apple.com
Thu May 3 14:19:36 PDT 2012


Author: jingham
Date: Thu May  3 16:19:36 2012
New Revision: 156101

URL: http://llvm.org/viewvc/llvm-project?rev=156101&view=rev
Log:
Clean up the usage of "MasterPlan" status in ThreadPlans.  Only user-initiated plans
should be MasterPlans that want to stay on the plan stack.  So make all plans NOT
MasterPlans by default and then have the SB API's and the CommandObjectThread step
commands set this explicitly.

Also added a "clean up" phase to the Thread::ShouldStop so that if plans get stranded
on the stack, we can remove them.  This is done by adding an IsPlanStale method to the
thread plans, and if the plan can know that it is no longer relevant, it returns true,
and the plan and its sub-plans will get discarded.

Modified:
    lldb/trunk/include/lldb/API/SBThread.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/include/lldb/Target/ThreadPlan.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlan.cpp
    lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
    lldb/trunk/source/Target/ThreadPlanStepOut.cpp
    lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
    lldb/trunk/source/Target/ThreadPlanStepRange.cpp
    lldb/trunk/source/Target/ThreadPlanStepUntil.cpp
    lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj

Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Thu May  3 16:19:36 2012
@@ -172,6 +172,11 @@
     void
     SetThread (const lldb::ThreadSP& lldb_object_sp);
 
+#ifndef SWIG
+    SBError
+    ResumeNewPlan (lldb_private::ExecutionContext &exe_ctx, lldb_private::ThreadPlan *new_plan);
+#endif
+
 private:
     lldb::ExecutionContextRefSP m_opaque_sp;
 };

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Thu May  3 16:19:36 2012
@@ -674,6 +674,9 @@
     void
     DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp);
 
+    void
+    DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr);
+    
     //------------------------------------------------------------------
     /// Prints the current plan stack.
     ///

Modified: lldb/trunk/include/lldb/Target/ThreadPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlan.h?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlan.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlan.h Thu May  3 16:19:36 2012
@@ -115,12 +115,33 @@
 //  figure out what to do about the plans below it in the stack.  If the stop is recoverable, then the plan that
 //  understands it can just do what it needs to set up to restart, and then continue.
 //  Otherwise, the plan that understood the stop should call DiscardPlanStack to clean up the stack below it.
-//  In the normal case, this will just collapse the plan stack up to the point of the plan that understood
+//
+//  Master plans:
+//
+//  In the normal case, when we decide to stop, we will  collapse the plan stack up to the point of the plan that understood
 //  the stop reason.  However, if a plan wishes to stay on the stack after an event it didn't directly handle
 //  it can designate itself a "Master" plan by responding true to IsMasterPlan, and then if it wants not to be
 //  discarded, it can return true to OkayToDiscard, and it and all its dependent plans will be preserved when
 //  we resume execution.
 //
+//  The other effect of being a master plan is that when the Master plan is done , if it has set "OkayToDiscard" to false,
+//  then it will be popped & execution will stop and return to the user.  Remember that if OkayToDiscard is false, the
+//  plan will be popped and control will be given to the next plan above it on the stack  So setting OkayToDiscard to
+//  false means the user will regain control when the MasterPlan is completed.
+//
+//  Between these two controls this allows things like: a MasterPlan/DontDiscard Step Over to hit a breakpoint, stop and
+//  return control to the user, but then when the user continues, the step out succeeds.
+//  Even more tricky, when the breakpoint is hit, the user can continue to step in/step over/etc, and finally when they
+//  continue, they will finish up the Step Over.
+//
+//  FIXME: MasterPlan & OkayToDiscard aren't really orthogonal.  MasterPlan designation means that this plan controls
+//  it's fate and the fate of plans below it.  OkayToDiscard tells whether the MasterPlan wants to stay on the stack.  I
+//  originally thought "MasterPlan-ness" would need to be a fixed characteristic of a ThreadPlan, in which case you needed
+//  the extra control.  But that doesn't seem to be true.  So we should be able to convert to only MasterPlan status to mean
+//  the current "MasterPlan/DontDiscard".  Then no plans would be MasterPlans by default, and you would set the ones you
+//  wanted to be "user level" in this way.
+//
+//
 //  Actually Stopping:
 //
 //  If a plan says responds "true" to ShouldStop, then it is asked if it's job is complete by calling
@@ -152,6 +173,18 @@
 //  because of a crash or breakpoint hit, it wants to unship itself, because it isn't so useful to have step in keep going
 //  after a breakpoint hit.  But it can't be the reason for the stop or no-one would see that they had hit a breakpoint.
 //
+//  Cleaning up the plan stack:
+//
+//  One of the complications of MasterPlans is that you may get past the limits of a plan without triggering it to clean
+//  itself up.  For instance, if you are doing a MasterPlan StepOver, and hit a breakpoint in a called function, then
+//  step over enough times to step out of the initial StepOver range, each of the step overs will explain the stop & 
+//  take themselves off the stack, but control would never be returned to the original StepOver.  Eventually, the user 
+//  will continue, and when that continue stops, the old stale StepOver plan that was left on the stack will get woken 
+//  up and notice it is done. But that can leave junk on the stack for a while.  To avoid that, the plans implement a
+//  "IsPlanStale" method, that can check whether it is relevant anymore.  On stop, after the regular plan negotiation, 
+//  the remaining plan stack is consulted and if any plan says it is stale, it and the plans below it are discarded from
+//  the stack.
+//
 //  Automatically Resuming:
 //
 //  If ShouldStop for all threads returns "false", then the target process will resume.  This then cycles back to
@@ -408,6 +441,12 @@
     void
     SetPlanComplete (bool success = true);
     
+    virtual bool
+    IsPlanStale ()
+    {
+        return false;
+    }
+    
     bool
     PlanSucceeded ()
     {

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepOut.h Thu May  3 16:19:36 2012
@@ -42,6 +42,7 @@
     virtual bool WillStop ();
     virtual bool MischiefManaged ();
     virtual void DidPush();
+    virtual bool IsPlanStale();
     
     virtual lldb::ValueObjectSP GetReturnValueObject()
     {

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h Thu May  3 16:19:36 2012
@@ -28,8 +28,7 @@
     ThreadPlanStepOverRange (Thread &thread, 
                              const AddressRange &range, 
                              const SymbolContext &addr_context, 
-                             lldb::RunMode stop_others, 
-                             bool okay_to_discard = false);
+                             lldb::RunMode stop_others);
                              
     virtual ~ThreadPlanStepOverRange ();
 

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepRange.h Thu May  3 16:19:36 2012
@@ -43,6 +43,7 @@
     virtual bool WillStop ();
     virtual bool MischiefManaged ();
     virtual void DidPush ();
+    virtual bool IsPlanStale ();
 
 
     void AddRange(const AddressRange &new_range);

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu May  3 16:19:36 2012
@@ -4082,10 +4082,7 @@
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				ARCHS = "$(NATIVE_ARCH)";
 				"ARCHS[sdk=iphoneos*]" = armv7;
-				"ARCHS[sdk=macosx*]" = (
-					x86_64,
-					i386,
-				);
+				"ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)";
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				GCC_C_LANGUAGE_STANDARD = gnu99;

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Thu May  3 16:19:36 2012
@@ -474,6 +474,47 @@
     return name;
 }
 
+SBError
+SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan)
+{
+    SBError sb_error;
+    
+    Process *process = exe_ctx.GetProcessPtr();
+    if (!process)
+    {
+        sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
+        return sb_error;
+    }
+
+    Thread *thread = exe_ctx.GetThreadPtr();
+    if (!thread)
+    {
+        sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
+        return sb_error;
+    }
+    
+    // User level plans should be Master Plans so they can be interrupted, other plans executed, and
+    // then a "continue" will resume the plan.
+    if (new_plan != NULL)
+    {
+        new_plan->SetIsMasterPlan(true);
+        new_plan->SetOkayToDiscard(false);
+    }
+    
+    // Why do we need to set the current thread by ID here???
+    process->GetThreadList().SetSelectedThreadByID (thread->GetID());
+    sb_error.ref() = process->Resume();
+    
+    if (sb_error.Success())
+    {
+        // If we are doing synchronous mode, then wait for the
+        // process to stop yet again!
+        if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
+            process->WaitForProcessToStop (NULL);
+    }
+    
+    return sb_error;
+}
 
 void
 SBThread::StepOver (lldb::RunMode stop_other_threads)
@@ -492,39 +533,31 @@
         Thread *thread = exe_ctx.GetThreadPtr();
         bool abort_other_plans = true;
         StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
+        ThreadPlan *new_plan = NULL;
 
         if (frame_sp)
         {
             if (frame_sp->HasDebugInformation ())
             {
                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
-                thread->QueueThreadPlanForStepRange (abort_other_plans, 
-                                                     eStepTypeOver,
-                                                     sc.line_entry.range, 
-                                                     sc,
-                                                     stop_other_threads,
-                                                     false);
+                new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
+                                                                eStepTypeOver,
+                                                                sc.line_entry.range,
+                                                                sc,
+                                                                stop_other_threads,
+                                                                false);
                 
             }
             else
             {
-                thread->QueueThreadPlanForStepSingleInstruction (true, 
-                                                                 abort_other_plans, 
-                                                                 stop_other_threads);
+                new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
+                                                                            abort_other_plans, 
+                                                                            stop_other_threads);
             }
         }
 
-        Process *process = exe_ctx.GetProcessPtr();
-        // Why do we need to set the current thread by ID here???
-        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-        Error error (process->Resume());
-        if (error.Success())
-        {
-            // If we are doing synchronous mode, then wait for the
-            // process to stop yet again!
-            if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                process->WaitForProcessToStop (NULL);
-        }
+        // This returns an error, we should use it!
+        ResumeNewPlan (exe_ctx, new_plan);
     }
 }
 
@@ -545,36 +578,28 @@
 
         Thread *thread = exe_ctx.GetThreadPtr();
         StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
+        ThreadPlan *new_plan = NULL;
 
         if (frame_sp && frame_sp->HasDebugInformation ())
         {
             bool avoid_code_without_debug_info = true;
             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
-            thread->QueueThreadPlanForStepRange (abort_other_plans, 
-                                                 eStepTypeInto, 
-                                                 sc.line_entry.range, 
-                                                 sc, 
-                                                 stop_other_threads,
-                                                 avoid_code_without_debug_info);
+            new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
+                                                            eStepTypeInto,
+                                                            sc.line_entry.range,
+                                                            sc,
+                                                            stop_other_threads,
+                                                            avoid_code_without_debug_info);
         }
         else
         {
-            thread->QueueThreadPlanForStepSingleInstruction (false, 
-                                                             abort_other_plans, 
-                                                             stop_other_threads);
-        }
-
-        Process *process = exe_ctx.GetProcessPtr();
-        // Why do we need to set the current thread by ID here???
-        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-        Error error (process->Resume());
-        if (error.Success())
-        {
-            // If we are doing synchronous mode, then wait for the
-            // process to stop yet again!
-            if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                process->WaitForProcessToStop (NULL);
+            new_plan = thread->QueueThreadPlanForStepSingleInstruction (false,
+                                                                        abort_other_plans, 
+                                                                        stop_other_threads);
         }
+        
+        // This returns an error, we should use it!
+        ResumeNewPlan (exe_ctx, new_plan);
     }
 }
 
@@ -596,24 +621,16 @@
 
         Thread *thread = exe_ctx.GetThreadPtr();
 
-        thread->QueueThreadPlanForStepOut (abort_other_plans, 
-                                              NULL, 
-                                              false, 
-                                              stop_other_threads, 
-                                              eVoteYes, 
-                                              eVoteNoOpinion,
-                                              0);
-        
-        Process *process = exe_ctx.GetProcessPtr();
-        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-        Error error (process->Resume());
-        if (error.Success())
-        {
-            // If we are doing synchronous mode, then wait for the
-            // process to stop yet again!
-            if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                process->WaitForProcessToStop (NULL);
-        }
+        ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
+                                                                  NULL, 
+                                                                  false, 
+                                                                  stop_other_threads, 
+                                                                  eVoteYes, 
+                                                                  eVoteNoOpinion,
+                                                                  0);
+                                                                  
+        // This returns an error, we should use it!
+        ResumeNewPlan (exe_ctx, new_plan);
     }
 }
 
@@ -638,24 +655,16 @@
         bool stop_other_threads = true;
         Thread *thread = exe_ctx.GetThreadPtr();
 
-        thread->QueueThreadPlanForStepOut (abort_other_plans, 
-                                              NULL, 
-                                              false, 
-                                              stop_other_threads, 
-                                              eVoteYes, 
-                                              eVoteNoOpinion,
-                                              frame_sp->GetFrameIndex());
-        
-        Process *process = exe_ctx.GetProcessPtr();
-        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-        Error error (process->Resume());
-        if (error.Success())
-        {
-            // If we are doing synchronous mode, then wait for the
-            // process to stop yet again!
-            if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                process->WaitForProcessToStop (NULL);
-        }
+        ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
+                                                                    NULL, 
+                                                                    false, 
+                                                                    stop_other_threads, 
+                                                                    eVoteYes, 
+                                                                    eVoteNoOpinion,
+                                                                    frame_sp->GetFrameIndex());
+                                                                    
+        // This returns an error, we should use it!
+        ResumeNewPlan (exe_ctx, new_plan);
     }
 }
 
@@ -674,17 +683,10 @@
     {
         Mutex::Locker api_locker (exe_ctx.GetTargetPtr()->GetAPIMutex());
         Thread *thread = exe_ctx.GetThreadPtr();
-        Process *process = exe_ctx.GetProcessPtr();
-        thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
-        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-        Error error (process->Resume());
-        if (error.Success())
-        {
-            // If we are doing synchronous mode, then wait for the
-            // process to stop yet again!
-            if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                process->WaitForProcessToStop (NULL);
-        }
+        ThreadPlan *new_plan = thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
+        
+        // This returns an error, we should use it!
+        ResumeNewPlan (exe_ctx, new_plan);
     }
 }
 
@@ -707,18 +709,11 @@
         Address target_addr (addr);
 
         Thread *thread = exe_ctx.GetThreadPtr();
-        Process *process = exe_ctx.GetProcessPtr();
 
-        thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
-        process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-        Error error (process->Resume());
-        if (error.Success())
-        {
-            // If we are doing synchronous mode, then wait for the
-            // process to stop yet again!
-            if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                process->WaitForProcessToStop (NULL);
-        }
+        ThreadPlan *new_plan = thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
+        
+        // This returns an error, we should use it!
+        ResumeNewPlan (exe_ctx, new_plan);
     }
 }
 
@@ -854,23 +849,13 @@
         }
         else
         {
-            thread->QueueThreadPlanForStepUntil (abort_other_plans, 
-                                                 &step_over_until_addrs[0],
-                                                 step_over_until_addrs.size(),
-                                                 stop_other_threads,
-                                                 frame_sp->GetFrameIndex());      
-
-            Process *process = exe_ctx.GetProcessPtr();
-
-            process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-            sb_error.ref() = process->Resume();
-            if (sb_error->Success())
-            {
-                // If we are doing synchronous mode, then wait for the
-                // process to stop yet again!
-                if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
-                    process->WaitForProcessToStop (NULL);
-            }
+            ThreadPlan *new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans,
+                                                                        &step_over_until_addrs[0],
+                                                                        step_over_until_addrs.size(),
+                                                                        stop_other_threads,
+                                                                        frame_sp->GetFrameIndex());      
+
+            sb_error = ResumeNewPlan (exe_ctx, new_plan);
         }
     }
     else

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Thu May  3 16:19:36 2012
@@ -451,10 +451,11 @@
             else
                 bool_stop_other_threads = true;
 
+            ThreadPlan *new_plan = NULL;
+            
             if (m_step_type == eStepTypeInto)
             {
                 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
-                ThreadPlan *new_plan;
 
                 if (frame->HasDebugInformation ())
                 {
@@ -471,14 +472,11 @@
                 }
                 else
                     new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
-
-                process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-                process->Resume ();
+                    
             }
             else if (m_step_type == eStepTypeOver)
             {
                 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
-                ThreadPlan *new_plan;
 
                 if (frame->HasDebugInformation())
                     new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 
@@ -492,29 +490,17 @@
                                                                                 abort_other_plans, 
                                                                                 bool_stop_other_threads);
 
-                // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
-                // Maybe there should be a parameter to control this.
-                new_plan->SetOkayToDiscard(false);
-
-                process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-                process->Resume ();
             }
             else if (m_step_type == eStepTypeTrace)
             {
-                thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
-                process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-                process->Resume ();
+                new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
             }
             else if (m_step_type == eStepTypeTraceOver)
             {
-                thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
-                process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-                process->Resume ();
+                new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
             }
             else if (m_step_type == eStepTypeOut)
             {
-                ThreadPlan *new_plan;
-
                 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, 
                                                               NULL, 
                                                               false, 
@@ -522,32 +508,46 @@
                                                               eVoteYes, 
                                                               eVoteNoOpinion, 
                                                               thread->GetSelectedFrameIndex());
-                // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
-                // Maybe there should be a parameter to control this.
-                new_plan->SetOkayToDiscard(false);
-
-                process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-                process->Resume ();
             }
             else
             {
                 result.AppendError ("step type is not supported");
                 result.SetStatus (eReturnStatusFailed);
+                return false;
             }
-            if (synchronous_execution)
+            
+            // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
+            // so that they can be interruptible).  Then resume the process.
+            
+            if (new_plan != NULL)
             {
-                StateType state = process->WaitForProcessToStop (NULL);
-                
-                //EventSP event_sp;
-                //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
-                //while (! StateIsStoppedState (state))
-                //  {
-                //    state = process->WaitForStateChangedEvents (NULL, event_sp);
-                //  }
+                new_plan->SetIsMasterPlan (true);
+                new_plan->SetOkayToDiscard (false);
+
                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
-                result.SetDidChangeProcessState (true);
-                result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
-                result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                process->Resume ();
+            
+
+                if (synchronous_execution)
+                {
+                    StateType state = process->WaitForProcessToStop (NULL);
+                    
+                    //EventSP event_sp;
+                    //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
+                    //while (! StateIsStoppedState (state))
+                    //  {
+                    //    state = process->WaitForStateChangedEvents (NULL, event_sp);
+                    //  }
+                    process->GetThreadList().SetSelectedThreadByID (thread->GetID());
+                    result.SetDidChangeProcessState (true);
+                    result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
+                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+                }
+            }
+            else
+            {
+                result.AppendError ("Couldn't find thread plan to implement step type.");
+                result.SetStatus (eReturnStatusFailed);
             }
         }
         return result.Succeeded();
@@ -959,7 +959,7 @@
                 return false;
             }
 
-            ThreadPlan *new_plan;
+            ThreadPlan *new_plan = NULL;
 
             if (frame->HasDebugInformation ())
             {
@@ -1027,6 +1027,10 @@
                                                                 address_list.size(), 
                                                                 m_options.m_stop_others, 
                                                                 thread->GetSelectedFrameIndex ());
+                // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
+                // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
+                // will resume the original plan.
+                new_plan->SetIsMasterPlan (true);
                 new_plan->SetOkayToDiscard(false);
             }
             else

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu May  3 16:19:36 2012
@@ -455,8 +455,33 @@
                 }
             }
         }
+        
         if (over_ride_stop)
             should_stop = false;
+
+        // One other potential problem is that we set up a master plan, then stop in before it is complete - for instance
+        // by hitting a breakpoint during a step-over - then do some step/finish/etc operations that wind up
+        // past the end point condition of the initial plan.  We don't want to strand the original plan on the stack,
+        // This code clears stale plans off the stack.
+        
+        if (should_stop)
+        {
+            ThreadPlan *plan_ptr = GetCurrentPlan();
+            while (!PlanIsBasePlan(plan_ptr))
+            {
+                bool stale = plan_ptr->IsPlanStale ();
+                ThreadPlan *examined_plan = plan_ptr;
+                plan_ptr = GetPreviousPlan (examined_plan);
+                
+                if (stale)
+                {
+                    if (log)
+                        log->Printf("Plan %s being discarded in cleanup, it says it is already done.", examined_plan->GetName());
+                    DiscardThreadPlansUpToPlan(examined_plan);
+                }
+            }
+        }
+        
     }
 
     if (log)
@@ -750,10 +775,16 @@
 void
 Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
 {
+    DiscardThreadPlansUpToPlan (up_to_plan_sp.get());
+}
+
+void
+Thread::DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr)
+{
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     if (log)
     {
-        log->Printf("Discarding thread plans for thread tid = 0x%4.4llx, up to %p", GetID(), up_to_plan_sp.get());
+        log->Printf("Discarding thread plans for thread tid = 0x%4.4llx, up to %p", GetID(), up_to_plan_ptr);
     }
 
     int stack_size = m_plan_stack.size();
@@ -761,7 +792,7 @@
     // If the input plan is NULL, discard all plans.  Otherwise make sure this plan is in the
     // stack, and if so discard up to and including it.
     
-    if (up_to_plan_sp.get() == NULL)
+    if (up_to_plan_ptr == NULL)
     {
         for (int i = stack_size - 1; i > 0; i--)
             DiscardPlan();
@@ -771,7 +802,7 @@
         bool found_it = false;
         for (int i = stack_size - 1; i > 0; i--)
         {
-            if (m_plan_stack[i] == up_to_plan_sp)
+            if (m_plan_stack[i].get() == up_to_plan_ptr)
                 found_it = true;
         }
         if (found_it)
@@ -779,7 +810,7 @@
             bool last_one = false;
             for (int i = stack_size - 1; i > 0 && !last_one ; i--)
             {
-                if (GetCurrentPlan() == up_to_plan_sp.get())
+                if (GetCurrentPlan() == up_to_plan_ptr)
                     last_one = true;
                 DiscardPlan();
             }

Modified: lldb/trunk/source/Target/ThreadPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlan.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlan.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlan.cpp Thu May  3 16:19:36 2012
@@ -36,7 +36,7 @@
     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
     m_plan_complete (false),
     m_plan_private (false),
-    m_okay_to_discard (false),
+    m_okay_to_discard (true),
     m_is_master_plan (false),
     m_plan_succeeded(true)
 {

Modified: lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp Thu May  3 16:19:36 2012
@@ -131,7 +131,13 @@
                     s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
                     log->Printf("%s.", s.GetData());
                 }
-                m_thread.QueueThreadPlanForStepOut(false, NULL, true, m_stop_other_threads, eVoteNo, eVoteNoOpinion, 0);
+                m_thread.QueueThreadPlanForStepOut(false,
+                                                   NULL,
+                                                   true,
+                                                   m_stop_other_threads,
+                                                   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=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepOut.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepOut.cpp Thu May  3 16:19:36 2012
@@ -81,7 +81,6 @@
                                                             eVoteNoOpinion, 
                                                             eVoteNoOpinion, 
                                                             frame_idx - 1));
-            m_step_out_plan_sp->SetOkayToDiscard(true);
         }
         else
         {
@@ -468,3 +467,17 @@
         }
     }
 }
+
+bool
+ThreadPlanStepOut::IsPlanStale()
+{
+    // If we are still lower on the stack than the frame we are returning to, then
+    // there's something for us to do.  Otherwise, we're stale.
+    
+    StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
+    if (frame_zero_id < m_step_out_to_id)
+        return false;
+    else
+        return true;
+}
+

Modified: lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepOverRange.cpp Thu May  3 16:19:36 2012
@@ -38,15 +38,10 @@
     Thread &thread,
     const AddressRange &range,
     const SymbolContext &addr_context,
-    lldb::RunMode stop_others,
-    bool okay_to_discard
+    lldb::RunMode stop_others
 ) :
     ThreadPlanStepRange (ThreadPlan::eKindStepOverRange, "Step range stepping over", thread, range, addr_context, stop_others)
 {
-    // Step over range plans can be master plans, since you could hit a breakpoint while stepping over, step around
-    // a bit, then continue to finish up the step over.
-    SetIsMasterPlan (true);
-    SetOkayToDiscard (okay_to_discard);
 }
 
 ThreadPlanStepOverRange::~ThreadPlanStepOverRange ()

Modified: lldb/trunk/source/Target/ThreadPlanStepRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepRange.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepRange.cpp Thu May  3 16:19:36 2012
@@ -403,3 +403,30 @@
     }
 
 }
+
+bool
+ThreadPlanStepRange::IsPlanStale ()
+{
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    FrameComparison frame_order = CompareCurrentFrameToStartFrame();
+    
+    if (frame_order == eFrameCompareOlder)
+    {
+        if (log)
+        {
+            log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out.");
+        }
+        return true;
+    }
+    else if (frame_order == eFrameCompareEqual && InSymbol())
+    {
+        // If we are not in a place we should step through, we've gotten stale.
+        // One tricky bit here is that some stubs don't push a frame, so we should.  
+        // check that we are in the same symbol.          
+        if (!InRange())
+        {
+            return true;
+        }
+    }
+    return false;
+}

Modified: lldb/trunk/source/Target/ThreadPlanStepUntil.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepUntil.cpp?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepUntil.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepUntil.cpp Thu May  3 16:19:36 2012
@@ -51,12 +51,6 @@
     m_until_points (),
     m_stop_others (stop_others)
 {
-
-    // Step until plans can be master plans, since you could hit a breakpoint while stepping to the stop point, step around
-    // a bit, then continue to finish up the step until.
-    SetIsMasterPlan (true);
-    SetOkayToDiscard(true);
-    
     // Stash away our "until" addresses:
     TargetSP target_sp (m_thread.CalculateTarget());
 

Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=156101&r1=156100&r2=156101&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Thu May  3 16:19:36 2012
@@ -514,10 +514,7 @@
 					armv7,
 					armv7s,
 				);
-				"ARCHS[sdk=macosx*]" = (
-					x86_64,
-					i386,
-				);
+				"ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_64_BIT)";
 				CURRENT_PROJECT_VERSION = 186;
 				DEAD_CODE_STRIPPING = YES;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;





More information about the lldb-commits mailing list