labath created this revision.
labath added reviewers: tberghammer, emaste.
labath added subscribers: lldb-commits, abhishek.aggarwal.
Herald added a subscriber: emaste.

r259344 introduced a bug, where we fail to perform a single step, when the 
instruction we are
stepping onto contains a breakpoint which is not valid for this thread. This 
fixes the problem
and add a test case.

http://reviews.llvm.org/D16767

Files:
  
packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestSingleStepOntoBreakpoint.py
  source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -2006,19 +2006,10 @@
 
                             // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
                             // Otherwise, it will be set to Trace.
-                            if (bp_site_sp)
+                            if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
                             {
-                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
-                                // we can just report no reason.
-                                if (bp_site_sp->ValidForThisThread (thread_sp.get()))
-                                {
-                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
-                                }
-                                else
-                                {
-                                    StopInfoSP invalid_stop_info_sp;
-                                    thread_sp->SetStopInfo (invalid_stop_info_sp);
-                                }
+                                thread_sp->SetStopInfo(
+                                    StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
                             }
                             else
                               thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
Index: source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
===================================================================
--- source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -569,20 +569,11 @@
 
     // If the current pc is a breakpoint site then set the StopInfo to Breakpoint.
     // Otherwise, set the StopInfo to Watchpoint or Trace.
-    if (bp_site)
-    {
-        lldb::break_id_t bp_id = bp_site->GetID();
-        // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
-        // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
-        // report the breakpoint regardless of the thread.
-        if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)
-            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
-        else
-        {
-            const bool should_stop = false;
-            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
-        }
-    }
+    // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
+    // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
+    // report the breakpoint regardless of the thread.
+    if (bp_site && (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL))
+        SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
     else
     {
         POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
Index: packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestSingleStepOntoBreakpoint.py
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestSingleStepOntoBreakpoint.py
@@ -0,0 +1,77 @@
+"""
+Test continue from a breakpoint when there is a breakpoint on the next instruction also.
+"""
+
+from __future__ import print_function
+
+
+
+import unittest2
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+class SingleStepOntoBreakpointTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @no_debug_info_test
+    def test_thread_specific_breakpoint(self):
+        self.run_test(True)
+
+    @no_debug_info_test
+    def test_general_breakpoint(self):
+        self.run_test(False)
+
+    def run_test(self, thread_specific):
+        self.build()
+        exe = os.path.join (os.getcwd(), "a.out")
+
+        # Create a target by the debugger.
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        breakpoint1 = target.BreakpointCreateBySourceRegex("Set breakpoint here", lldb.SBFileSpec("main.cpp"))
+        self.assertTrue(breakpoint1 and
+                        breakpoint1.GetNumLocations() == 1,
+                        VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at entry point.
+        process = target.LaunchSimple (None, None, self.get_process_working_directory())
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        # We should be stopped at the first breakpoint
+        thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint1)
+        self.assertIsNotNone(thread, "Expected one thread to be stopped at breakpoint 1")
+
+        # Set breakpoint to the next instruction
+        frame = thread.GetFrameAtIndex(0)
+
+        address = frame.GetPCAddress()
+        instructions = target.ReadInstructions(address, 2)
+        self.assertTrue(len(instructions) == 2)
+        address = instructions[1].GetAddress().GetLoadAddress(target)
+
+        breakpoint2 = target.BreakpointCreateByAddress(address)
+
+        if thread_specific:
+            thread_index = process.GetNumThreads()+1 # deliberately choose a non-existing thread
+            self.assertFalse(process.GetThreadAtIndex(thread_index).IsValid())
+            breakpoint2.SetThreadIndex(thread_index)
+
+        step_over = False
+        thread.StepInstruction(step_over)
+
+        self.assertEquals(thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress(target), address)
+        # In any case, we should have stopped, but the stop reason will be different depending on
+        # whether the breakpoint fired.
+        if thread_specific:
+            self.assertEquals(thread.GetStopReason(), lldb.eStopReasonPlanComplete,
+                    "Stop reason should be 'plan complete'")
+        else:
+            thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint2)
+            self.assertIsNotNone(thread, "Expected one thread to be stopped at breakpoint 2")
+
+        # Run the process until termination
+        process.Continue()
+        self.assertEquals(process.GetState(), lldb.eStateExited)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to