The step by running from branch to branch pretty much works with this checkin (at...
authorJim Ingham <jingham@apple.com>
Wed, 13 Mar 2013 01:56:41 +0000 (01:56 +0000)
committerJim Ingham <jingham@apple.com>
Wed, 13 Mar 2013 01:56:41 +0000 (01:56 +0000)
turned off, it needs more qualification.  If you want to play with it, change the initialization of m_use_fast_step
to true.

llvm-svn: 176923

lldb/include/lldb/Target/ThreadPlanStepRange.h
lldb/source/Target/ThreadPlanStepRange.cpp

index f53e4d8..486fd65 100644 (file)
@@ -81,6 +81,7 @@ protected:
                                                  // but can't continue, in which case we are done.
     bool                      m_first_run_event; // We want to broadcast only one running event, our first.
     lldb::BreakpointSP        m_next_branch_bp_sp;
+    bool                      m_use_fast_step;
 
 private:
     std::vector<lldb::DisassemblerSP> m_instruction_ranges;
index 912e087..5204806 100644 (file)
@@ -15,6 +15,8 @@
 // Project includes
 
 #include "lldb/lldb-private-log.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSite.h"
 #include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Stream.h"
@@ -49,7 +51,8 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
     m_stop_others (stop_others),
     m_stack_id (),
     m_no_more_plans (false),
-    m_first_run_event (true)
+    m_first_run_event (true),
+    m_use_fast_step(false)
 {
     AddRange(range);
     m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
@@ -300,6 +303,9 @@ ThreadPlanStepRange::ClearNextBranchBreakpoint()
 {
     if (m_next_branch_bp_sp)
     {
+        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+        if (log)
+            log->Printf ("Removing next branch breakpoint: %d.", m_next_branch_bp_sp->GetID());
         GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID());
         m_next_branch_bp_sp.reset();
     }
@@ -308,11 +314,15 @@ ThreadPlanStepRange::ClearNextBranchBreakpoint()
 bool
 ThreadPlanStepRange::SetNextBranchBreakpoint ()
 {
+    if (m_next_branch_bp_sp)
+        return true;
+
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction
     // single stepping.
-    return false;
-    // Always clear the next branch breakpoint, we don't want to leave one of these stranded.
-    ClearNextBranchBreakpoint();
+    if (!m_use_fast_step)
+         return false;
+
     lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
     // Find the current address in our address ranges, and fetch the disassembly if we haven't already:
     size_t pc_index;
@@ -330,8 +340,9 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
         // If we didn't find a branch, run to the end of the range.
         if (branch_index == UINT32_MAX)
         {
-            branch_index = instructions->GetSize() - 2;
+            branch_index = instructions->GetSize() - 1;
         }
+        
         if (branch_index - pc_index > 1)
         {
             const bool is_internal = true;
@@ -339,8 +350,26 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
             m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal);
             if (m_next_branch_bp_sp)
             {
+                if (log)
+                {
+                    lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
+                    BreakpointLocationSP bp_loc = m_next_branch_bp_sp->GetLocationAtIndex(0);
+                    if (bp_loc)
+                    {
+                        BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
+                        if (bp_site)
+                        {
+                            bp_site_id = bp_site->GetID();
+                        }
+                    }
+                    log->Printf ("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting breakpoint %d (site %d) to run to address 0x%" PRIx64,
+                                 m_next_branch_bp_sp->GetID(),
+                                 bp_site_id,
+                                 run_to_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget()));
+                }
                 m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
                 m_next_branch_bp_sp->SetBreakpointKind ("next-branch-location");
+                return true;
             }
             else
                 return false;
@@ -352,15 +381,39 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
 bool
 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp)
 {
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     if (!m_next_branch_bp_sp)
         return false;
     
     break_id_t bp_site_id = stop_info_sp->GetValue();
     BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id);
-    if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID()))
+    if (!bp_site_sp)
+        return false;
+    else if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID()))
         return false;
     else
-        return bp_site_sp->GetNumberOfOwners() == 1;
+    {
+        // If we've hit the next branch breakpoint, then clear it.
+        size_t num_owners = bp_site_sp->GetNumberOfOwners();
+        bool explains_stop = true;
+        // If all the owners are internal, then we are probably just stepping over this range from multiple threads,
+        // or multiple frames, so we want to continue.  If one is not internal, then we should not explain the stop,
+        // and let the user breakpoint handle the stop.
+        for (size_t i = 0; i < num_owners; i++)
+        {
+            if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
+            {
+                explains_stop = false;
+                break;
+            }
+        }
+        if (log)
+            log->Printf ("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit next range breakpoint which has %zu owners - explains stop: %u.",
+                        num_owners,
+                        explains_stop);
+        ClearNextBranchBreakpoint();
+        return  explains_stop;
+    }
 }
 
 bool
@@ -416,6 +469,7 @@ ThreadPlanStepRange::MischiefManaged ()
         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
         if (log)
             log->Printf("Completed step through range plan.");
+        ClearNextBranchBreakpoint();
         ThreadPlan::MischiefManaged ();
         return true;
     }