1""" 2Watch 4 bytes which spawn two doubleword aligned regions. 3On a target that supports 8 byte watchpoints, this will 4need to be implemented with a hardware watchpoint on both 5doublewords. 6""" 7 8 9import lldb 10from lldbsuite.test.decorators import * 11from lldbsuite.test.lldbtest import * 12from lldbsuite.test import lldbutil 13 14 15class UnalignedWatchpointTestCase(TestBase): 16 def hit_watchpoint_and_continue(self, process, iter_str): 17 process.Continue() 18 self.assertEqual(process.GetState(), lldb.eStateStopped, iter_str) 19 thread = process.GetSelectedThread() 20 self.assertEqual(thread.GetStopReason(), lldb.eStopReasonWatchpoint, iter_str) 21 self.assertEqual(thread.GetStopReasonDataCount(), 1, iter_str) 22 wp_num = thread.GetStopReasonDataAtIndex(0) 23 self.assertEqual(wp_num, 1, iter_str) 24 25 NO_DEBUG_INFO_TESTCASE = True 26 27 # debugserver on AArch64 has this feature. 28 @skipIf(archs=no_match(["arm64", "arm64e", "aarch64"])) 29 @skipUnlessDarwin 30 # debugserver only started returning an exception address within 31 # a range lldb expects in https://reviews.llvm.org/D147820 2023-04-12. 32 # older debugservers will return the base address of the doubleword 33 # which lldb doesn't understand, and will stop executing without a 34 # proper stop reason. 35 @skipIfOutOfTreeDebugserver 36 def test_unaligned_watchpoint(self): 37 """Test a watchpoint that is handled by two hardware watchpoint registers.""" 38 self.build() 39 self.main_source_file = lldb.SBFileSpec("main.c") 40 (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 41 self, "break here", self.main_source_file 42 ) 43 44 thread.StepOver() 45 46 frame = thread.GetFrameAtIndex(0) 47 48 a_bytebuf_6 = frame.GetValueForVariablePath("a.bytebuf[6]") 49 a_bytebuf_6_addr = a_bytebuf_6.GetAddress().GetLoadAddress(target) 50 err = lldb.SBError() 51 wp_opts = lldb.SBWatchpointOptions() 52 wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify) 53 wp = target.WatchpointCreateByAddress(a_bytebuf_6_addr, 4, wp_opts, err) 54 self.assertTrue(err.Success()) 55 self.assertTrue(wp.IsEnabled()) 56 self.assertEqual(wp.GetWatchSize(), 4) 57 self.assertGreater( 58 wp.GetWatchAddress() % 8, 4, "watched region spans two doublewords" 59 ) 60 61 # We will hit our watchpoint 6 times during the execution 62 # of the inferior. If the remote stub does not actually split 63 # the watched region into two doubleword watchpoints, we will 64 # exit before we get to 6 watchpoint hits. 65 for i in range(1, 7): 66 self.hit_watchpoint_and_continue(process, "wp hit number %s" % i) 67