xref: /llvm-project/lldb/test/API/python_api/watchpoint/TestSetWatchpoint.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1"""
2Use lldb Python SBValue API to create a watchpoint for read_write of 'globl' var.
3"""
4
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import lldbutil
9
10
11class SetWatchpointAPITestCase(TestBase):
12    NO_DEBUG_INFO_TESTCASE = True
13
14    def setUp(self):
15        # Call super's setUp().
16        TestBase.setUp(self)
17        # Our simple source filename.
18        self.source = "main.c"
19        # Find the line number to break inside main().
20        self.line = line_number(self.source, "// Set break point at this line.")
21        self.build()
22
23    # Read-write watchpoints not supported on SystemZ
24    @expectedFailureAll(archs=["s390x"])
25    def test_watch_val(self):
26        """Exercise SBValue.Watch() API to set a watchpoint."""
27        self._test_watch_val(variable_watchpoint=False)
28        pass
29
30    @expectedFailureAll(archs=["s390x"])
31    def test_watch_variable(self):
32        """
33        Exercise some watchpoint APIs when the watchpoint
34        is created as a variable watchpoint.
35        """
36        self._test_watch_val(variable_watchpoint=True)
37
38    def _test_watch_val(self, variable_watchpoint):
39        exe = self.getBuildArtifact("a.out")
40
41        # Create a target by the debugger.
42        target = self.dbg.CreateTarget(exe)
43        self.assertTrue(target, VALID_TARGET)
44
45        # Now create a breakpoint on main.c.
46        breakpoint = target.BreakpointCreateByLocation(self.source, self.line)
47        self.assertTrue(
48            breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT
49        )
50
51        # Now launch the process, and do not stop at the entry point.
52        process = target.LaunchSimple(None, None, self.get_process_working_directory())
53
54        # We should be stopped due to the breakpoint.  Get frame #0.
55        process = target.GetProcess()
56        self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
57        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
58        frame0 = thread.GetFrameAtIndex(0)
59
60        # Watch 'global' for read and write.
61        if variable_watchpoint:
62            # FIXME: There should probably be an API to create a
63            # variable watchpoint.
64            self.runCmd("watchpoint set variable -w read_write -- global")
65            watchpoint = target.GetWatchpointAtIndex(0)
66            self.assertEqual(
67                watchpoint.GetWatchValueKind(), lldb.eWatchPointValueKindVariable
68            )
69            self.assertEqual(watchpoint.GetWatchSpec(), "global")
70            # Synthesize an SBValue from the watchpoint
71            watchpoint_addr = lldb.SBAddress(watchpoint.GetWatchAddress(), target)
72            value = target.CreateValueFromAddress(
73                watchpoint.GetWatchSpec(), watchpoint_addr, watchpoint.GetType()
74            )
75        else:
76            value = frame0.FindValue("global", lldb.eValueTypeVariableGlobal)
77            error = lldb.SBError()
78            watchpoint = value.Watch(True, True, True, error)
79            self.assertTrue(
80                value and watchpoint,
81                "Successfully found the variable and set a watchpoint",
82            )
83            self.DebugSBValue(value)
84            self.assertEqual(
85                watchpoint.GetWatchValueKind(), lldb.eWatchPointValueKindExpression
86            )
87            # FIXME: The spec should probably be '&global' given that the kind
88            # is reported as eWatchPointValueKindExpression. If the kind is
89            # actually supposed to be eWatchPointValueKindVariable then the spec
90            # should probably be 'global'.
91            self.assertEqual(watchpoint.GetWatchSpec(), None)
92
93        self.assertEqual(watchpoint.GetType().GetDisplayTypeName(), "int32_t")
94        self.assertEqual(value.GetName(), "global")
95        self.assertEqual(value.GetType(), watchpoint.GetType())
96        self.assertTrue(watchpoint.IsWatchingReads())
97        self.assertTrue(watchpoint.IsWatchingWrites())
98
99        # Hide stdout if not running with '-t' option.
100        if not self.TraceOn():
101            self.HideStdout()
102
103        print(watchpoint)
104
105        # Continue.  Expect the program to stop due to the variable being
106        # written to.
107        process.Continue()
108
109        if self.TraceOn():
110            lldbutil.print_stacktraces(process)
111
112        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint)
113        self.assertTrue(thread, "The thread stopped due to watchpoint")
114        self.DebugSBValue(value)
115
116        # Continue.  Expect the program to stop due to the variable being read
117        # from.
118        process.Continue()
119
120        if self.TraceOn():
121            lldbutil.print_stacktraces(process)
122
123        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint)
124        self.assertTrue(thread, "The thread stopped due to watchpoint")
125        self.DebugSBValue(value)
126
127        # Continue the process.  We don't expect the program to be stopped
128        # again.
129        process.Continue()
130
131        # At this point, the inferior process should have exited.
132        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
133
134        self.dbg.DeleteTarget(target)
135        self.assertFalse(watchpoint.IsValid())
136