https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/218883
Follow up to #218819. It was agreed in https://discourse.llvm.org/t/running-lldb-in-a-container/76801/1 that we would default to ALSR being on during the test suite. This means people don't have to reconfigure their systems to run our tests out of the box. So we need to look before we run a test that needs to disable ASLR. Here I am adding a decorator to do that. It assumes it's always allowed on MacOS and uses personality (https://man7.org/linux/man-pages/man2/personality.2.html) to check if we can change it on Linux. Since we're calling personality on the test process, this cannot be done for a remote target. We could go launch a process but for the added complexity I didn't think the extra coverage was worth it. So "Not able to disable ASLR" is a bit of a simplification because sometimes we might be able to but didn't check. >From 20772b81312ff96b4f85a47251f5aea444b8d2b6 Mon Sep 17 00:00:00 2001 From: Jason Molenda <[email protected]> Date: Tue, 25 Aug 2026 18:07:09 -0700 Subject: [PATCH 1/3] [lldb] When re-enabling a watchpoint, save the current bytes A watchpoint holds the current byte values of the memory region it is watching. When we have a watchpoint in place and re-run, the saved values are flushed. If the user then re-enables that watchpoint in the next Process launch, we need to collect the current values again for the Watchpoint at that point. The test depends on watching a byte range that does not change across process launch. On Darwin systems, macOS is the only one that can disable ASLR. I don't know if this test can be enabled on Linux with the disable-ASLR process launch option. rdar://184927603 --- lldb/source/Breakpoint/Watchpoint.cpp | 5 ++ .../run-reenable-watchpoint/Makefile | 3 ++ .../TestRunReEnableWatchpoint.py | 51 +++++++++++++++++++ .../watchpoint/run-reenable-watchpoint/main.c | 7 +++ 4 files changed, 66 insertions(+) create mode 100644 lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/Makefile create mode 100644 lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py create mode 100644 lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c diff --git a/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp index e839c8b9f30e7..13bc2556a9b9c 100644 --- a/lldb/source/Breakpoint/Watchpoint.cpp +++ b/lldb/source/Breakpoint/Watchpoint.cpp @@ -421,6 +421,11 @@ void Watchpoint::SetEnabled(bool enabled, bool notify) { } bool changed = enabled != m_enabled; m_enabled = enabled; + if (enabled && !m_new_value_sp && m_target.GetProcessSP()) { + ExecutionContext exe_ctx; + m_target.GetProcessSP()->CalculateExecutionContext(exe_ctx); + CaptureWatchedValue(exe_ctx); + } if (notify && !m_is_ephemeral && changed) SendWatchpointChangedEvent(enabled ? eWatchpointEventTypeEnabled : eWatchpointEventTypeDisabled); diff --git a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/Makefile b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/Makefile new file mode 100644 index 0000000000000..10495940055b6 --- /dev/null +++ b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py new file mode 100644 index 0000000000000..a380ac3f66d58 --- /dev/null +++ b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py @@ -0,0 +1,51 @@ +""" +Test that a watchpoint created in one Process can be +re-enabled in a second Process launch and behave +correctly. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class RunReEnableWatchpointTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def continue_and_report_stop_reason(self, process, iter_str): + process.Continue() + self.assertIn( + process.GetState(), [lldb.eStateStopped, lldb.eStateExited], iter_str + ) + thread = process.GetSelectedThread() + return thread.GetStopReason() + + # We must be able to launch the inferior with ASLR disabled + # so the static array lands at the same address after relaunch. + @skipUnlessPlatform(["macosx"]) + def test_rerun_enable_watchpoint(self): + """Test set watchpoint, re-run, re-enable wp, hit it.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + li = lldb.SBLaunchInfo(None) + li.SetLaunchFlags(lldb.eLaunchFlagDisableASLR) + target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, "break here", self.main_source_file, launch_info=li + ) + + frame = thread.GetFrameAtIndex(0) + self.runCmd("watch set variable arr") + + reason = self.continue_and_report_stop_reason(process, "continue first-launch") + self.assertEqual(reason, lldb.eStopReasonWatchpoint) + + process.Kill() + self.runCmd("process launch --disable-aslr true") + process = target.GetProcess() + self.assertTrue(process.IsValid()) + + target.EnableAllWatchpoints() + + reason = self.continue_and_report_stop_reason(process, "continue second-launch") + self.assertEqual(reason, lldb.eStopReasonWatchpoint) diff --git a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c new file mode 100644 index 0000000000000..35dfe48967755 --- /dev/null +++ b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c @@ -0,0 +1,7 @@ +static int arr[] = {1, 2, 0, 3, 4, 0x55555555}; +int main() +{ + arr[0]++; // break here + arr[0]++; + return arr[4]; +} >From 0f600633b365102c54ca04626399d84e69868ead Mon Sep 17 00:00:00 2001 From: Jason Molenda <[email protected]> Date: Tue, 25 Aug 2026 18:36:35 -0700 Subject: [PATCH 2/3] ws --- .../watchpoint/run-reenable-watchpoint/main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c index 35dfe48967755..0969dd247bf74 100644 --- a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c +++ b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/main.c @@ -1,7 +1,6 @@ static int arr[] = {1, 2, 0, 3, 4, 0x55555555}; -int main() -{ - arr[0]++; // break here - arr[0]++; - return arr[4]; +int main() { + arr[0]++; // break here + arr[0]++; + return arr[4]; } >From 0fa367adf12487f885f6cbd045b4dbd380964838 Mon Sep 17 00:00:00 2001 From: David Spickett <[email protected]> Date: Wed, 26 Aug 2026 10:24:10 +0000 Subject: [PATCH 3/3] [lldb][test] Add requiresDisableASLR test decorator Follow up to #218819. It was agreed in https://discourse.llvm.org/t/running-lldb-in-a-container/76801/1 that we would default to ALSR being on during the test suite. This means people don't have to reconfigure their systems to run our tests out of the box. So we need to look before we run a test that needs to disable ASLR. Here I am adding a decorator to do that. It assumes it's always allowed on MacOS and uses personality (https://man7.org/linux/man-pages/man2/personality.2.html) to check if we can change it on Linux. Since we're calling personality on the test process, this cannot be done for a remote target. We could go launch a process but for the added complexity I didn't think the extra coverage was worth it. So "Not able to disable ASLR" is a bit of a simplification because sometimes we might be able to but didn't check. --- .../Python/lldbsuite/test/decorators.py | 40 +++++++++++++++++++ .../TestRunReEnableWatchpoint.py | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index 306eb20622746..6c02b56d2645f 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -1289,6 +1289,46 @@ def requireThreadSupport(func): )(func) +def _can_disable_aslr(): + original_persona = None + GET_CURRENT_PERSONA = 0xFFFFFFFF + ADDR_NO_RANDOMIZE = 0x0040000 + ERR = -1 + + libc = ctypes.CDLL(None) + personality = libc.personality + personality.argtypes = [ctypes.c_ulong] + personality.restype = ctypes.c_int + + try: + original_persona = personality(GET_CURRENT_PERSONA) + if original_persona == ERR: + return False + + if personality(original_persona | ADDR_NO_RANDOMIZE) == ERR: + return False + + new_persona = personality(GET_CURRENT_PERSONA) + if new_persona == ERR: + return False + + return new_persona & ADDR_NO_RANDOMIZE + finally: + if original_persona is not None: + personality(original_persona) + + +def requireDisableASLR(func): + platform = lldbplatformutil.getPlatform() + return unittest.skipIf( + platform != "macosx" + and not ( + lldb.remote_platform is None and platform == "linux" and _can_disable_aslr() + ), + UnsupportedReason(f"Not able to disable ASLR"), + )(func) + + def skipIfTargetDoesNotSupportSharedLibraries(): """Skip tests that require shared library (dylib/so) support.""" platform = lldbplatformutil.getPlatform() diff --git a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py index a380ac3f66d58..6b18e460dcb99 100644 --- a/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py +++ b/lldb/test/API/functionalities/watchpoint/run-reenable-watchpoint/TestRunReEnableWatchpoint.py @@ -23,7 +23,7 @@ def continue_and_report_stop_reason(self, process, iter_str): # We must be able to launch the inferior with ASLR disabled # so the static array lands at the same address after relaunch. - @skipUnlessPlatform(["macosx"]) + @requireDisableASLR def test_rerun_enable_watchpoint(self): """Test set watchpoint, re-run, re-enable wp, hit it.""" self.build() _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
