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) 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: 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));