[Lldb-commits] [lldb] [lldb][test] Refactor TestMemoryRegionDirtyPages.py (PR #156035)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 29 07:46:20 PDT 2025
https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/156035
This started as me being annoyed that I got loads of this when inspecting memory regions on Mac:
Modified memory (dirty) page list provided, 0 entries.
So I thought I should test the existing behaviour, which lead me to refactor the existing test to run the same checks on all regions.
In the process I realised that the output is not wrong. There is a difference between knowing that no pages are dirty and not knowing anything about dirty pages. We print that there are 0 entries so the user knows that difference.
The test case now checks "memory region" output as well as API use. There were also some checks only run on certain regions, like page size, which now run for all of them.
>From 497e39baf65ab19bdc85ae3f7c2d165f52d00599 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Fri, 29 Aug 2025 13:51:40 +0000
Subject: [PATCH] [lldb][test] Refactor TestMemoryRegionDirtyPages.py
This started as me being annoyed that I got loads of this when
inspecting memory regions on Mac:
Modified memory (dirty) page list provided, 0 entries.
So I thought I should test the existing behaviour, which lead
me to refactor the existing test to run the same checks on all
regions.
In the process I realised that the output is not wrong. There is
a difference between knowing that no pages are dirty and not knowing
anything about dirty pages. So saying 0 are currently dirty is in
fact correct.
So the test now checks "memory region" output as well as API use.
There were also some checks only run on certain regions, like page
size, which now run for all of them.
---
.../TestMemoryRegionDirtyPages.py | 118 ++++++++++++------
1 file changed, 80 insertions(+), 38 deletions(-)
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestMemoryRegionDirtyPages.py b/lldb/test/API/functionalities/gdb_remote_client/TestMemoryRegionDirtyPages.py
index 9d7e0c0f7af6c..695faf896ef5d 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestMemoryRegionDirtyPages.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestMemoryRegionDirtyPages.py
@@ -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,
+ )
More information about the lldb-commits
mailing list