Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,102 @@
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase


class TestRegion(object):
def __init__(self, start_addr, size, dirty_pages):
self.start_addr = start_addr
self.size = size
self.dirty_pages = dirty_pages

def as_packet(self):
dirty_pages = ""
if self.dirty_pages is not None:
dirty_pages = (
"dirty-pages:"
+ ",".join([format(a, "x") for a in self.dirty_pages])
+ ";"
)
return f"start:{self.start_addr:x};size:{self.size};permissions:r;{dirty_pages}"

def expected_command_output(self):
if self.dirty_pages is None:
return [
"Modified memory (dirty) page list provided",
"Dirty pages:",
], False

expected = [
f"Modified memory (dirty) page list provided, {len(self.dirty_pages)} entries."
]
if self.dirty_pages:
expected.append(
"Dirty pages: "
+ ", ".join([format(a, "#x") for a in self.dirty_pages])
+ "."
)
return expected, True


class TestMemoryRegionDirtyPages(GDBRemoteTestBase):
@skipIfXmlSupportMissing
def test(self):
test_regions = [
# A memory region where we don't know anything about dirty pages
TestRegion(0, 0x100000000, None),
# A memory region with dirty page information -- and zero dirty pages
TestRegion(0x100000000, 4000, []),
# A memory region with one dirty page
TestRegion(0x100004000, 4000, [0x100004000]),
# A memory region with multple dirty pages
TestRegion(
0x1000A2000,
5000,
[0x1000A2000, 0x1000A3000, 0x1000A4000, 0x1000A5000, 0x1000A6000],
),
]

class MyResponder(MockGDBServerResponder):
def qHostInfo(self):
return "ptrsize:8;endian:little;vm-page-size:4096;"

def qMemoryRegionInfo(self, addr):
if addr == 0:
return "start:0;size:100000000;"
if addr == 0x100000000:
return "start:100000000;size:4000;permissions:rx;dirty-pages:;"
if addr == 0x100004000:
return (
"start:100004000;size:4000;permissions:r;dirty-pages:100004000;"
)
if addr == 0x1000A2000:
return "start:1000a2000;size:5000;permissions:r;dirty-pages:1000a2000,1000a3000,1000a4000,1000a5000,1000a6000;"
for region in test_regions:
if region.start_addr == addr:
return region.as_packet()

self.server.responder = MyResponder()
target = self.dbg.CreateTarget("")
if self.TraceOn():
self.runCmd("log enable gdb-remote packets")
self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets"))

process = self.connect(target)
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)

# A memory region where we don't know anything about dirty pages
region = lldb.SBMemoryRegionInfo()
err = process.GetMemoryRegionInfo(0, region)
self.assertSuccess(err)
self.assertFalse(region.HasDirtyMemoryPageList())
self.assertEqual(region.GetNumDirtyPages(), 0)
region.Clear()
for test_region in test_regions:
region = lldb.SBMemoryRegionInfo()
err = process.GetMemoryRegionInfo(test_region.start_addr, region)
self.assertSuccess(err)
self.assertEqual(region.GetPageSize(), 4096)

# A memory region with dirty page information -- and zero dirty pages
err = process.GetMemoryRegionInfo(0x100000000, region)
self.assertSuccess(err)
self.assertTrue(region.HasDirtyMemoryPageList())
self.assertEqual(region.GetNumDirtyPages(), 0)
self.assertEqual(region.GetPageSize(), 4096)
region.Clear()
if test_region.dirty_pages is None:
self.assertFalse(region.HasDirtyMemoryPageList())
self.assertEqual(0, region.GetNumDirtyPages())
else:
self.assertTrue(region.HasDirtyMemoryPageList())
self.assertEqual(
len(test_region.dirty_pages), region.GetNumDirtyPages()
)

# A memory region with one dirty page
err = process.GetMemoryRegionInfo(0x100004000, region)
self.assertSuccess(err)
self.assertTrue(region.HasDirtyMemoryPageList())
self.assertEqual(region.GetNumDirtyPages(), 1)
self.assertEqual(region.GetDirtyPageAddressAtIndex(0), 0x100004000)
region.Clear()
for i, expected_dirty_page in enumerate(test_region.dirty_pages):
self.assertEqual(
expected_dirty_page, region.GetDirtyPageAddressAtIndex(i)
)

# A memory region with multple dirty pages
err = process.GetMemoryRegionInfo(0x1000A2000, region)
self.assertSuccess(err)
self.assertTrue(region.HasDirtyMemoryPageList())
self.assertEqual(region.GetNumDirtyPages(), 5)
self.assertEqual(region.GetDirtyPageAddressAtIndex(4), 0x1000A6000)
region.Clear()
substrs, matching = test_region.expected_command_output()
self.expect(
f"memory region 0x{test_region.start_addr:x}",
substrs=substrs,
matching=matching,
)
Loading