| """ |
| Watch contiguous memory regions with separate watchpoints, check that lldb |
| correctly detect which watchpoint was hit for each one. |
| """ |
| |
| import lldb |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| |
| |
| class ConsecutiveWatchpointsTestCase(TestBase): |
| NO_DEBUG_INFO_TESTCASE = True |
| |
| def continue_and_report_stop_reason(self, process, iter_str): |
| process.Continue() |
| self.assertIn( |
| process.GetState(), [lldb.eStateStopped, lldb.eStateExited], iter_str |
| ) |
| thread = process.GetSelectedThread() |
| return thread.GetStopReason() |
| |
| # debugserver only gained the ability to watch larger regions |
| # with this patch. |
| @skipIfOutOfTreeDebugserver |
| def test_consecutive_watchpoints(self): |
| """Test watchpoint that covers a large region of memory.""" |
| self.build() |
| self.main_source_file = lldb.SBFileSpec("main.c") |
| (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( |
| self, "break here", self.main_source_file |
| ) |
| |
| frame = thread.GetFrameAtIndex(0) |
| |
| field2_wp = ( |
| frame.locals["var"][0] |
| .GetChildMemberWithName("field2") |
| .Watch(True, False, True) |
| ) |
| field3_wp = ( |
| frame.locals["var"][0] |
| .GetChildMemberWithName("field3") |
| .Watch(True, False, True) |
| ) |
| field4_wp = ( |
| frame.locals["var"][0] |
| .GetChildMemberWithName("field4") |
| .Watch(True, False, True) |
| ) |
| field5_wp = ( |
| frame.locals["var"][0] |
| .GetChildMemberWithName("field5") |
| .Watch(True, False, True) |
| ) |
| |
| # Require that the first two watchpoints |
| # are set -- hopefully every machine running |
| # the testsuite can support two watchpoints. |
| self.assertTrue(field2_wp.IsValid()) |
| self.assertTrue(field3_wp.IsValid()) |
| |
| reason = self.continue_and_report_stop_reason(process, "continue to field2 wp") |
| self.assertEqual(reason, lldb.eStopReasonWatchpoint) |
| stop_reason_watchpoint_id = ( |
| process.GetSelectedThread().GetStopReasonDataAtIndex(0) |
| ) |
| self.assertEqual(stop_reason_watchpoint_id, field2_wp.GetID()) |
| |
| reason = self.continue_and_report_stop_reason(process, "continue to field3 wp") |
| self.assertEqual(reason, lldb.eStopReasonWatchpoint) |
| stop_reason_watchpoint_id = ( |
| process.GetSelectedThread().GetStopReasonDataAtIndex(0) |
| ) |
| self.assertEqual(stop_reason_watchpoint_id, field3_wp.GetID()) |
| |
| # If we were able to set the second two watchpoints, |
| # check that they are hit. Some CI bots can only |
| # create two watchpoints. |
| if field4_wp.IsValid() and field5_wp.IsValid(): |
| reason = self.continue_and_report_stop_reason( |
| process, "continue to field4 wp" |
| ) |
| self.assertEqual(reason, lldb.eStopReasonWatchpoint) |
| stop_reason_watchpoint_id = ( |
| process.GetSelectedThread().GetStopReasonDataAtIndex(0) |
| ) |
| self.assertEqual(stop_reason_watchpoint_id, field4_wp.GetID()) |
| |
| reason = self.continue_and_report_stop_reason( |
| process, "continue to field5 wp" |
| ) |
| self.assertEqual(reason, lldb.eStopReasonWatchpoint) |
| stop_reason_watchpoint_id = ( |
| process.GetSelectedThread().GetStopReasonDataAtIndex(0) |
| ) |
| self.assertEqual(stop_reason_watchpoint_id, field5_wp.GetID()) |