1""" 2Watch a large unaligned memory region that 3lldb will need multiple hardware watchpoints 4to cover. 5""" 6 7 8import lldb 9from lldbsuite.test.decorators import * 10from lldbsuite.test.lldbtest import * 11from lldbsuite.test import lldbutil 12 13 14class UnalignedLargeWatchpointTestCase(TestBase): 15 def continue_and_report_stop_reason(self, process, iter_str): 16 if self.TraceOn(): 17 self.runCmd("script print('continue')") 18 process.Continue() 19 self.assertIn( 20 process.GetState(), [lldb.eStateStopped, lldb.eStateExited], iter_str 21 ) 22 thread = process.GetSelectedThread() 23 return thread.GetStopReason() 24 25 NO_DEBUG_INFO_TESTCASE = True 26 27 # The Windows process plugins haven't been updated to break 28 # watchpoints into WatchpointResources yet. 29 @skipIfWindows 30 31 # Test on 64-bit targets where we probably have 32 # four watchpoint registers that can watch doublewords (8-byte). 33 @skipIf(archs=no_match(["arm64", "arm64e", "aarch64", "x86_64"])) 34 def test_unaligned_large_watchpoint(self): 35 """Test watching an unaligned region of memory that requires multiple watchpoints.""" 36 self.build() 37 self.main_source_file = lldb.SBFileSpec("main.c") 38 target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( 39 self, "break here", self.main_source_file 40 ) 41 self.runCmd("break set -p done") 42 self.runCmd("break set -p exiting") 43 44 frame = thread.GetFrameAtIndex(0) 45 46 array_addr = frame.GetValueForVariablePath("array").GetValueAsUnsigned() 47 48 # Don't assume that the heap allocated array is aligned 49 # to a 1024 byte boundary to begin with, force alignment. 50 # wa_addr = (array_addr + 1024) & ~(1024 - 1) 51 wa_addr = array_addr 52 53 # Now make the start address unaligned. 54 wa_addr = wa_addr + 7 55 56 err = lldb.SBError() 57 wp_opts = lldb.SBWatchpointOptions() 58 wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify) 59 wp = target.WatchpointCreateByAddress(wa_addr, 22, wp_opts, err) 60 self.assertTrue(wp.IsValid()) 61 self.assertSuccess(err) 62 if self.TraceOn(): 63 self.runCmd("watch list -v") 64 65 c_count = 0 66 reason = self.continue_and_report_stop_reason(process, "continue #%d" % c_count) 67 while reason == lldb.eStopReasonWatchpoint: 68 c_count = c_count + 1 69 reason = self.continue_and_report_stop_reason( 70 process, "continue #%d" % c_count 71 ) 72 self.assertLessEqual(c_count, 22) 73 74 self.assertEqual(c_count, 22) 75 self.expect("watchpoint list -v", substrs=["hit_count = 22"]) 76 self.assertEqual(wp.GetHitCount(), 22) 77 78 target.DeleteWatchpoint(wp.GetID()) 79 80 # Now try watching a 16 byte variable 81 # (not unaligned, but a good check to do anyway) 82 frame = thread.GetFrameAtIndex(0) 83 err = lldb.SBError() 84 wp = frame.locals["variable"][0].Watch(True, False, True, err) 85 self.assertSuccess(err) 86 if self.TraceOn(): 87 self.runCmd("frame select 0") 88 self.runCmd("watchpoint list") 89 90 c_count = 0 91 reason = self.continue_and_report_stop_reason(process, "continue #%d" % c_count) 92 while reason == lldb.eStopReasonWatchpoint: 93 c_count = c_count + 1 94 reason = self.continue_and_report_stop_reason( 95 process, "continue #%d" % c_count 96 ) 97 self.assertLessEqual(c_count, 4) 98 99 if self.TraceOn(): 100 self.runCmd("frame select 0") 101 102 self.assertEqual(c_count, 4) 103 self.expect("watchpoint list -v", substrs=["hit_count = 4"]) 104 self.assertEqual(wp.GetHitCount(), 4) 105