[Lldb-commits] [lldb] [lldb] Fix crash after second run when set a previous watchpoint. (PR #136682)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 24 02:20:43 PDT 2025
https://github.com/hapeeeeee updated https://github.com/llvm/llvm-project/pull/136682
>From 563cbddfe9b7da394c818a03e05924c0f7d39d5f Mon Sep 17 00:00:00 2001
From: hapeeeeee <623151737 at qq.com>
Date: Tue, 22 Apr 2025 11:34:38 +0800
Subject: [PATCH 1/2] [lldb] Fix crash after second run when set a previous
watchpoint.
---
lldb/source/Breakpoint/Watchpoint.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp
index 2df848aaa0576..0fcc9b90c0ab5 100644
--- a/lldb/source/Breakpoint/Watchpoint.cpp
+++ b/lldb/source/Breakpoint/Watchpoint.cpp
@@ -409,6 +409,15 @@ bool Watchpoint::IsDisabledDuringEphemeralMode() {
}
void Watchpoint::SetEnabled(bool enabled, bool notify) {
+ // Whenever setting the enabled state of a watchpoint, we need to ensure
+ // that `m_new_value_sp` exists to avoid crash when reading old_data later.
+ // See https://github.com/llvm/llvm-project/issues/135590.
+ if (!m_new_value_sp) {
+ ExecutionContext exe_ctx;
+ m_target.GetProcessSP()->CalculateExecutionContext(exe_ctx);
+ CaptureWatchedValue(exe_ctx);
+ }
+
if (!enabled) {
if (m_is_ephemeral)
++m_disabled_count;
>From 980c9bc97011fa4fbce4f67688c3539f3d518a42 Mon Sep 17 00:00:00 2001
From: hapeeeeee <623151737 at qq.com>
Date: Wed, 23 Apr 2025 21:33:32 +0800
Subject: [PATCH 2/2] add testcase
---
.../Makefile | 3 +
.../TestReuseWatchpointAfterReExecProcess.py | 71 +++++++++++++++++++
.../main.c | 5 ++
3 files changed, 79 insertions(+)
create mode 100644 lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/Makefile
create mode 100644 lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/TestReuseWatchpointAfterReExecProcess.py
create mode 100644 lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/main.c
diff --git a/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/Makefile b/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/TestReuseWatchpointAfterReExecProcess.py b/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/TestReuseWatchpointAfterReExecProcess.py
new file mode 100644
index 0000000000000..d4b4afd538cde
--- /dev/null
+++ b/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/TestReuseWatchpointAfterReExecProcess.py
@@ -0,0 +1,71 @@
+"""
+Set a watchpoint on a variable, then kill the process and restart it with the same watchpoint.
+Check whether LLDB crashes due to a dangling pointer.
+"""
+
+import os
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestReuseWatchpointAfterReExecProcess(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()
+
+ # debugserver only gained the ability to watch larger regions
+ # with this patch.
+ def test_reuse_watchpoint_after_re_exec_process(self):
+ """Test watchpoint that covers a large region of memory."""
+ 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
+ )
+
+ frame = thread.GetFrameAtIndex(0)
+ var_wp = (
+ frame.locals["var"][0]
+ .Watch(True, False, True)
+ )
+ self.assertTrue(var_wp.IsValid())
+
+ # Kill the process and restart it with the same watchpoint.
+ process.Kill()
+ process = target.LaunchSimple(None, None, os.getcwd())
+ bkpt = target.BreakpointCreateBySourceRegex(
+ "break here", self.main_source_file, None
+ )
+
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process, bkpt)
+ thread = threads[0]
+ frame = thread.GetFrameAtIndex(0)
+
+ var_reused_wp = (
+ frame.locals["var"][0]
+ .Watch(True, False, True)
+ )
+
+ self.assertTrue(var_reused_wp.IsValid())
+ process.Continue()
+ reason = self.continue_and_report_stop_reason(process, "continue to reused var wp")
+ self.assertEqual(reason, lldb.eStopReasonWatchpoint)
+
+ stop_reason_watchpoint_id = (
+ process.GetSelectedThread().GetStopReasonDataAtIndex(0)
+ )
+ self.assertEqual(stop_reason_watchpoint_id, var_reused_wp.GetID())
+
+ # Check that the process exited, instead of crashing
+ process.Continue()
+ self.assertState(process.GetState(), lldb.eStateExited)
+
+
\ No newline at end of file
diff --git a/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/main.c b/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/main.c
new file mode 100644
index 0000000000000..8cf70d8b06d69
--- /dev/null
+++ b/lldb/test/API/functionalities/watchpoint/reuse-watchpoint-after-re-exec-process/main.c
@@ -0,0 +1,5 @@
+int main() {
+ int var;
+ var = 2; // break here
+ return 0;
+}
\ No newline at end of file
More information about the lldb-commits
mailing list