[Lldb-commits] [lldb] r295168 - Bug 30863 - Step doesn't stop with conditional breakpoint on the next line
Boris Ulasevich via lldb-commits
lldb-commits at lists.llvm.org
Wed Feb 15 03:42:48 PST 2017
Author: bulasevich
Date: Wed Feb 15 05:42:47 2017
New Revision: 295168
URL: http://llvm.org/viewvc/llvm-project?rev=295168&view=rev
Log:
Bug 30863 - Step doesn't stop with conditional breakpoint on the next line
Differential Revisions:
https://reviews.llvm.org/D26497 (committed r290168, temporary reverted r290197)
https://reviews.llvm.org/D28945 (fix for Ubuntu tests fail)
https://reviews.llvm.org/D29909 (fix for TestCallThatThrows test fail)
Added:
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py
lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp
Modified:
lldb/trunk/include/lldb/Target/Thread.h
lldb/trunk/include/lldb/Target/ThreadPlan.h
lldb/trunk/source/Target/Process.cpp
lldb/trunk/source/Target/StopInfo.cpp
lldb/trunk/source/Target/Thread.cpp
lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
lldb/trunk/source/Target/ThreadPlanStepRange.cpp
Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Wed Feb 15 05:42:47 2017
@@ -126,6 +126,7 @@ public:
// bit of data.
lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you
// might continue with the wrong signals.
+ std::vector<lldb::ThreadPlanSP> m_completed_plan_stack;
lldb::RegisterCheckpointSP
register_backup_sp; // You need to restore the registers, of course...
uint32_t current_inlined_depth;
@@ -1029,6 +1030,15 @@ public:
bool WasThreadPlanDiscarded(ThreadPlan *plan);
//------------------------------------------------------------------
+ /// Check if we have completed plan to override breakpoint stop reason
+ ///
+ /// @return
+ /// Returns true if completed plan stack is not empty
+ /// false otherwise.
+ //------------------------------------------------------------------
+ bool CompletedPlanOverridesBreakpoint();
+
+ //------------------------------------------------------------------
/// Queues a generic thread plan.
///
/// @param[in] plan_sp
@@ -1213,6 +1223,8 @@ public:
void SetStopInfo(const lldb::StopInfoSP &stop_info_sp);
+ void ResetStopInfo();
+
void SetShouldReportStop(Vote vote);
//----------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Target/ThreadPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlan.h?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlan.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlan.h Wed Feb 15 05:42:47 2017
@@ -40,9 +40,10 @@ namespace lldb_private {
// The thread maintaining a thread plan stack, and you program the actions of a
// particular thread
// by pushing plans onto the plan stack.
-// There is always a "Current" plan, which is the head of the plan stack,
+// There is always a "Current" plan, which is the top of the plan stack,
// though in some cases
-// a plan may defer to plans higher in the stack for some piece of information.
+// a plan may defer to plans higher in the stack for some piece of information
+// (let us define that the plan stack grows downwards).
//
// The plan stack is never empty, there is always a Base Plan which persists
// through the life
@@ -109,6 +110,15 @@ namespace lldb_private {
// plans in the time between when
// your plan gets unshipped and the next resume.
//
+// Thread State Checkpoint:
+//
+// Note that calling functions on target process (ThreadPlanCallFunction) changes
+// current thread state. The function can be called either by direct user demand or
+// internally, for example lldb allocates memory on device to calculate breakpoint
+// condition expression - on Linux it is performed by calling mmap on device.
+// ThreadStateCheckpoint saves Thread state (stop info and completed
+// plan stack) to restore it after completing function call.
+//
// Over the lifetime of the plan, various methods of the ThreadPlan are then
// called in response to changes of state in
// the process we are debugging as follows:
@@ -149,7 +159,7 @@ namespace lldb_private {
// If the Current plan answers "true" then it is asked if the stop should
// percolate all the way to the
// user by calling the ShouldStop method. If the current plan doesn't explain
-// the stop, then we query down
+// the stop, then we query up
// the plan stack for a plan that does explain the stop. The plan that does
// explain the stop then needs to
// figure out what to do about the plans below it in the stack. If the stop is
@@ -170,7 +180,7 @@ namespace lldb_private {
// 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
+// discarded, it can return false to OkayToDiscard, and it and all its dependent
// plans will be preserved when
// we resume execution.
//
@@ -207,7 +217,7 @@ namespace lldb_private {
//
// If a plan says responds "true" to ShouldStop, then it is asked if it's job
// is complete by calling
-// MischiefManaged. If that returns true, the thread is popped from the plan
+// MischiefManaged. If that returns true, the plan is popped from the plan
// stack and added to the
// Completed Plan Stack. Then the next plan in the stack is asked if it
// ShouldStop, and it returns "true",
@@ -241,9 +251,9 @@ namespace lldb_private {
//
// When the process stops, the thread is given a StopReason, in the form of a
// StopInfo object. If there is a completed
-// plan corresponding to the stop, then the "actual" stop reason will be
+// plan corresponding to the stop, then the "actual" stop reason can be
// suppressed, and instead a StopInfoThreadPlan
-// object will be cons'ed up from the highest completed plan in the stack.
+// object will be cons'ed up from the top completed plan in the stack.
// However, if the plan doesn't want to be
// the stop reason, then it can call SetPlanComplete and pass in "false" for
// the "success" parameter. In that case,
Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile?rev=295168&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile Wed Feb 15 05:42:47 2017
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+ifneq (,$(findstring icc,$(CC)))
+ CXXFLAGS += -debug inline-debug-info
+endif
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py?rev=295168&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py Wed Feb 15 05:42:47 2017
@@ -0,0 +1,119 @@
+"""
+Test that breakpoints do not affect stepping.
+Check for correct StopReason when stepping to the line with breakpoint
+which chould be eStopReasonBreakpoint in general,
+and eStopReasonPlanComplete when breakpoint's condition fails.
+"""
+
+from __future__ import print_function
+
+import unittest2
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class StepOverBreakpointsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ TestBase.setUp(self)
+
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+ src = lldb.SBFileSpec("main.cpp")
+
+ # Create a target by the debugger.
+ self.target = self.dbg.CreateTarget(exe)
+ self.assertTrue(self.target, VALID_TARGET)
+
+ # Setup four breakpoints, two of them with false condition
+ self.line1 = line_number('main.cpp', "breakpoint_1")
+ self.line4 = line_number('main.cpp', "breakpoint_4")
+
+ self.breakpoint1 = self.target.BreakpointCreateByLocation(src, self.line1)
+ self.assertTrue(
+ self.breakpoint1 and self.breakpoint1.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ self.breakpoint2 = self.target.BreakpointCreateBySourceRegex("breakpoint_2", src)
+ self.breakpoint2.GetLocationAtIndex(0).SetCondition('false')
+
+ self.breakpoint3 = self.target.BreakpointCreateBySourceRegex("breakpoint_3", src)
+ self.breakpoint3.GetLocationAtIndex(0).SetCondition('false')
+
+ self.breakpoint4 = self.target.BreakpointCreateByLocation(src, self.line4)
+
+ # Start debugging
+ self.process = self.target.LaunchSimple(
+ None, None, self.get_process_working_directory())
+ self.assertIsNotNone(self.process, PROCESS_IS_VALID)
+ self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint1)
+ self.assertIsNotNone(self.thread, "Didn't stop at breakpoint 1.")
+
+ def test_step_instruction(self):
+ # Count instructions between breakpoint_1 and breakpoint_4
+ contextList = self.target.FindFunctions('main', lldb.eFunctionNameTypeAuto)
+ self.assertEquals(contextList.GetSize(), 1)
+ symbolContext = contextList.GetContextAtIndex(0)
+ function = symbolContext.GetFunction()
+ self.assertTrue(function)
+ instructions = function.GetInstructions(self.target)
+ addr_1 = self.breakpoint1.GetLocationAtIndex(0).GetAddress()
+ addr_4 = self.breakpoint4.GetLocationAtIndex(0).GetAddress()
+ for i in range(instructions.GetSize()) :
+ addr = instructions.GetInstructionAtIndex(i).GetAddress()
+ if (addr == addr_1) : index_1 = i
+ if (addr == addr_4) : index_4 = i
+
+ steps_expected = index_4 - index_1
+ step_count = 0
+ # Step from breakpoint_1 to breakpoint_4
+ while True:
+ self.thread.StepInstruction(True)
+ step_count = step_count + 1
+ self.assertEquals(self.process.GetState(), lldb.eStateStopped)
+ self.assertTrue(self.thread.GetStopReason() == lldb.eStopReasonPlanComplete or
+ self.thread.GetStopReason() == lldb.eStopReasonBreakpoint)
+ if (self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) :
+ # we should not stop on breakpoint_2 and _3 because they have false condition
+ self.assertEquals(self.thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.line4)
+ # breakpoint_2 and _3 should not affect step count
+ self.assertTrue(step_count >= steps_expected)
+ break
+
+ # Run the process until termination
+ self.process.Continue()
+ self.assertEquals(self.process.GetState(), lldb.eStateExited)
+
+ def test_step_over(self):
+ #lldb.DBG.EnableLog("lldb", ["step","breakpoint"])
+
+ self.thread.StepOver()
+ # We should be stopped at the breakpoint_2 line with stop plan complete reason
+ self.assertEquals(self.process.GetState(), lldb.eStateStopped)
+ self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)
+
+ self.thread.StepOver()
+ # We should be stopped at the breakpoint_3 line with stop plan complete reason
+ self.assertEquals(self.process.GetState(), lldb.eStateStopped)
+ self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)
+
+ self.thread.StepOver()
+ # We should be stopped at the breakpoint_4
+ self.assertEquals(self.process.GetState(), lldb.eStateStopped)
+ self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint)
+ thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint4)
+ self.assertEquals(self.thread, thread1, "Didn't stop at breakpoint 4.")
+
+ # Check that stepping does not affect breakpoint's hit count
+ self.assertEquals(self.breakpoint1.GetHitCount(), 1)
+ self.assertEquals(self.breakpoint2.GetHitCount(), 0)
+ self.assertEquals(self.breakpoint3.GetHitCount(), 0)
+ self.assertEquals(self.breakpoint4.GetHitCount(), 1)
+
+ # Run the process until termination
+ self.process.Continue()
+ self.assertEquals(self.process.GetState(), lldb.eStateExited)
+
Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp?rev=295168&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp Wed Feb 15 05:42:47 2017
@@ -0,0 +1,12 @@
+
+int func() { return 1; }
+
+int
+main(int argc, char const *argv[])
+{
+ int a = 0; // breakpoint_1
+ int b = func(); // breakpoint_2
+ a = b + func(); // breakpoint_3
+ return 0; // breakpoint_4
+}
+
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed Feb 15 05:42:47 2017
@@ -5227,15 +5227,9 @@ Process::RunThreadPlan(ExecutionContext
do_resume = false;
handle_running_event = true;
} else {
- StopInfoSP stop_info_sp(thread_sp->GetStopInfo());
- StopReason stop_reason = eStopReasonInvalid;
- if (stop_info_sp)
- stop_reason = stop_info_sp->GetStopReason();
+ ThreadPlanSP plan = thread->GetCompletedPlan();
+ if (plan == thread_plan_sp && plan->PlanSucceeded()) {
- // FIXME: We only check if the stop reason is plan complete,
- // should we make sure that
- // it is OUR plan that is complete?
- if (stop_reason == eStopReasonPlanComplete) {
if (log)
log->PutCString("Process::RunThreadPlan(): execution "
"completed successfully.");
@@ -5246,9 +5240,11 @@ Process::RunThreadPlan(ExecutionContext
return_value = eExpressionCompleted;
} else {
+ StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
// Something restarted the target, so just wait for it to
// stop for real.
- if (stop_reason == eStopReasonBreakpoint) {
+ if (stop_info_sp &&
+ stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
if (log)
log->Printf("Process::RunThreadPlan() stopped for "
"breakpoint: %s.",
Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Wed Feb 15 05:42:47 2017
@@ -269,6 +269,7 @@ protected:
if (!m_should_perform_action)
return;
m_should_perform_action = false;
+ bool internal_breakpoint = true;
ThreadSP thread_sp(m_thread_wp.lock());
@@ -495,6 +496,9 @@ protected:
if (callback_says_stop)
m_should_stop = true;
+ if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())
+ internal_breakpoint = false;
+
// If we are going to stop for this breakpoint, then remove the
// breakpoint.
if (callback_says_stop && bp_loc_sp &&
@@ -526,6 +530,20 @@ protected:
"Process::%s could not find breakpoint site id: %" PRId64 "...",
__FUNCTION__, m_value);
}
+
+ if ((m_should_stop == false || internal_breakpoint)
+ && thread_sp->CompletedPlanOverridesBreakpoint()) {
+
+ // Override should_stop decision when we have
+ // completed step plan additionally to the breakpoint
+ m_should_stop = true;
+
+ // Here we clean the preset stop info so the next
+ // GetStopInfo call will find the appropriate stop info,
+ // which should be the stop info related to the completed plan
+ thread_sp->ResetStopInfo();
+ }
+
if (log)
log->Printf("Process::%s returning from action with m_should_stop: %d.",
__FUNCTION__, m_should_stop);
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Wed Feb 15 05:42:47 2017
@@ -380,24 +380,32 @@ lldb::StopInfoSP Thread::GetStopInfo() {
if (m_destroy_called)
return m_stop_info_sp;
- ThreadPlanSP plan_sp(GetCompletedPlan());
+ ThreadPlanSP completed_plan_sp(GetCompletedPlan());
ProcessSP process_sp(GetProcess());
const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;
- if (plan_sp && plan_sp->PlanSucceeded()) {
- return StopInfo::CreateStopReasonWithPlan(plan_sp, GetReturnValueObject(),
- GetExpressionVariable());
+
+ // Here we select the stop info according to priorirty:
+ // - m_stop_info_sp (if not trace) - preset value
+ // - completed plan stop info - new value with plan from completed plan stack
+ // - m_stop_info_sp (trace stop reason is OK now)
+ // - ask GetPrivateStopInfo to set stop info
+
+ bool have_valid_stop_info = m_stop_info_sp &&
+ m_stop_info_sp ->IsValid() &&
+ m_stop_info_stop_id == stop_id;
+ bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
+ bool plan_overrides_trace =
+ have_valid_stop_info && have_valid_completed_plan
+ && (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
+
+ if (have_valid_stop_info && !plan_overrides_trace) {
+ return m_stop_info_sp;
+ } else if (have_valid_completed_plan) {
+ return StopInfo::CreateStopReasonWithPlan(
+ completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
} else {
- if ((m_stop_info_stop_id == stop_id) || // Stop info is valid, just return
- // what we have (even if empty)
- (m_stop_info_sp &&
- m_stop_info_sp
- ->IsValid())) // Stop info is valid, just return what we have
- {
- return m_stop_info_sp;
- } else {
- GetPrivateStopInfo();
- return m_stop_info_sp;
- }
+ GetPrivateStopInfo();
+ return m_stop_info_sp;
}
}
@@ -459,6 +467,12 @@ bool Thread::StopInfoIsUpToDate() const
// date...
}
+void Thread::ResetStopInfo() {
+ if (m_stop_info_sp) {
+ m_stop_info_sp.reset();
+ }
+}
+
void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) {
m_stop_info_sp = stop_info_sp;
if (m_stop_info_sp) {
@@ -526,7 +540,8 @@ bool Thread::CheckpointThreadState(Threa
if (process_sp)
saved_state.orig_stop_id = process_sp->GetStopID();
saved_state.current_inlined_depth = GetCurrentInlinedDepth();
-
+ saved_state.m_completed_plan_stack = m_completed_plan_stack;
+
return true;
}
@@ -559,6 +574,7 @@ bool Thread::RestoreThreadStateFromCheck
SetStopInfo(saved_state.stop_info_sp);
GetStackFrameList()->SetCurrentInlinedDepth(
saved_state.current_inlined_depth);
+ m_completed_plan_stack = saved_state.m_completed_plan_stack;
return true;
}
@@ -895,6 +911,9 @@ bool Thread::ShouldStop(Event *event_ptr
if (should_stop) {
ThreadPlan *plan_ptr = GetCurrentPlan();
+
+ // Discard the stale plans and all plans below them in the stack,
+ // plus move the completed plans to the completed plan stack
while (!PlanIsBasePlan(plan_ptr)) {
bool stale = plan_ptr->IsPlanStale();
ThreadPlan *examined_plan = plan_ptr;
@@ -905,7 +924,15 @@ bool Thread::ShouldStop(Event *event_ptr
log->Printf(
"Plan %s being discarded in cleanup, it says it is already done.",
examined_plan->GetName());
- DiscardThreadPlansUpToPlan(examined_plan);
+ while (GetCurrentPlan() != examined_plan) {
+ DiscardPlan();
+ }
+ if (examined_plan->IsPlanComplete()) {
+ // plan is complete but does not explain the stop (example: step to a line
+ // with breakpoint), let us move the plan to completed_plan_stack anyway
+ PopPlan();
+ } else
+ DiscardPlan();
}
}
}
@@ -1133,6 +1160,10 @@ bool Thread::WasThreadPlanDiscarded(Thre
return false;
}
+bool Thread::CompletedPlanOverridesBreakpoint() {
+ return (!m_completed_plan_stack.empty()) ;
+}
+
ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) {
if (current_plan == nullptr)
return nullptr;
Modified: lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp Wed Feb 15 05:42:47 2017
@@ -94,6 +94,15 @@ bool ThreadPlanStepInstruction::IsPlanSt
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
if (cur_frame_id == m_stack_id) {
+ // Set plan Complete when we reach next instruction
+ uint64_t pc = m_thread.GetRegisterContext()->GetPC(0);
+ uint32_t max_opcode_size = m_thread.CalculateTarget()
+ ->GetArchitecture().GetMaximumOpcodeByteSize();
+ bool next_instruction_reached = (pc > m_instruction_addr) &&
+ (pc <= m_instruction_addr + max_opcode_size);
+ if (next_instruction_reached) {
+ SetPlanComplete();
+ }
return (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr);
} else if (cur_frame_id < m_stack_id) {
// If the current frame is younger than the start frame and we are stepping
Modified: lldb/trunk/source/Target/ThreadPlanStepRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepRange.cpp?rev=295168&r1=295167&r2=295168&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepRange.cpp Wed Feb 15 05:42:47 2017
@@ -461,6 +461,16 @@ bool ThreadPlanStepRange::IsPlanStale()
// 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()) {
+ // Set plan Complete when we reach next instruction just after the range
+ lldb::addr_t addr = m_thread.GetRegisterContext()->GetPC() - 1;
+ size_t num_ranges = m_address_ranges.size();
+ for (size_t i = 0; i < num_ranges; i++) {
+ bool in_range = m_address_ranges[i].ContainsLoadAddress(
+ addr, m_thread.CalculateTarget().get());
+ if (in_range) {
+ SetPlanComplete();
+ }
+ }
return true;
}
}
More information about the lldb-commits
mailing list