David Spickett had several suggestions for https://github.com/llvm/llvm-project/pull/79962 after I'd already merged it. Address those.
105 lines
3.7 KiB
Python
105 lines
3.7 KiB
Python
"""
|
|
Watch a large unaligned memory region that
|
|
lldb will need multiple hardware watchpoints
|
|
to cover.
|
|
"""
|
|
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test import lldbutil
|
|
|
|
|
|
class UnalignedLargeWatchpointTestCase(TestBase):
|
|
def continue_and_report_stop_reason(self, process, iter_str):
|
|
if self.TraceOn():
|
|
self.runCmd("script print('continue')")
|
|
process.Continue()
|
|
self.assertIn(
|
|
process.GetState(), [lldb.eStateStopped, lldb.eStateExited], iter_str
|
|
)
|
|
thread = process.GetSelectedThread()
|
|
return thread.GetStopReason()
|
|
|
|
NO_DEBUG_INFO_TESTCASE = True
|
|
|
|
# The Windows process plugins haven't been updated to break
|
|
# watchpoints into WatchpointResources yet.
|
|
@skipIfWindows
|
|
|
|
# Test on 64-bit targets where we probably have
|
|
# four watchpoint registers that can watch doublewords (8-byte).
|
|
@skipIf(archs=no_match(["arm64", "arm64e", "aarch64", "x86_64"]))
|
|
def test_unaligned_large_watchpoint(self):
|
|
"""Test watching an unaligned region of memory that requires multiple watchpoints."""
|
|
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
|
|
)
|
|
self.runCmd("break set -p done")
|
|
self.runCmd("break set -p exiting")
|
|
|
|
frame = thread.GetFrameAtIndex(0)
|
|
|
|
array_addr = frame.GetValueForVariablePath("array").GetValueAsUnsigned()
|
|
|
|
# Don't assume that the heap allocated array is aligned
|
|
# to a 1024 byte boundary to begin with, force alignment.
|
|
# wa_addr = (array_addr + 1024) & ~(1024 - 1)
|
|
wa_addr = array_addr
|
|
|
|
# Now make the start address unaligned.
|
|
wa_addr = wa_addr + 7
|
|
|
|
err = lldb.SBError()
|
|
wp_opts = lldb.SBWatchpointOptions()
|
|
wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)
|
|
wp = target.WatchpointCreateByAddress(wa_addr, 22, wp_opts, err)
|
|
self.assertTrue(wp.IsValid())
|
|
self.assertSuccess(err)
|
|
if self.TraceOn():
|
|
self.runCmd("watch list -v")
|
|
|
|
c_count = 0
|
|
reason = self.continue_and_report_stop_reason(process, "continue #%d" % c_count)
|
|
while reason == lldb.eStopReasonWatchpoint:
|
|
c_count = c_count + 1
|
|
reason = self.continue_and_report_stop_reason(
|
|
process, "continue #%d" % c_count
|
|
)
|
|
self.assertLessEqual(c_count, 22)
|
|
|
|
self.assertEqual(c_count, 22)
|
|
self.expect("watchpoint list -v", substrs=["hit_count = 22"])
|
|
self.assertEqual(wp.GetHitCount(), 22)
|
|
|
|
target.DeleteWatchpoint(wp.GetID())
|
|
|
|
# Now try watching a 16 byte variable
|
|
# (not unaligned, but a good check to do anyway)
|
|
frame = thread.GetFrameAtIndex(0)
|
|
err = lldb.SBError()
|
|
wp = frame.locals["variable"][0].Watch(True, False, True, err)
|
|
self.assertSuccess(err)
|
|
if self.TraceOn():
|
|
self.runCmd("frame select 0")
|
|
self.runCmd("watchpoint list")
|
|
|
|
c_count = 0
|
|
reason = self.continue_and_report_stop_reason(process, "continue #%d" % c_count)
|
|
while reason == lldb.eStopReasonWatchpoint:
|
|
c_count = c_count + 1
|
|
reason = self.continue_and_report_stop_reason(
|
|
process, "continue #%d" % c_count
|
|
)
|
|
self.assertLessEqual(c_count, 4)
|
|
|
|
if self.TraceOn():
|
|
self.runCmd("frame select 0")
|
|
|
|
self.assertEqual(c_count, 4)
|
|
self.expect("watchpoint list -v", substrs=["hit_count = 4"])
|
|
self.assertEqual(wp.GetHitCount(), 4)
|