xref: /llvm-project/lldb/test/API/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py (revision c73a3f16f81aaa427c61f69020a82b5b09570ffb)
1"""
2Use lldb Python SBtarget.WatchpointCreateByAddress() API to create a watchpoint for write of '*g_char_ptr'.
3"""
4
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import lldbutil
9
10
11class TargetWatchpointCreateByAddressPITestCase(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.cpp"
19        # Find the line number to break inside main().
20        self.line = line_number(self.source, "// Set break point at this line.")
21        # This is for verifying that watch location works.
22        self.violating_func = "do_bad_thing_with_location"
23
24    def test_watch_address(self):
25        """Exercise SBTarget.WatchpointCreateByAddress() API to set a watchpoint."""
26        self.build()
27        exe = self.getBuildArtifact("a.out")
28
29        # Create a target by the debugger.
30        target = self.dbg.CreateTarget(exe)
31        self.assertTrue(target, VALID_TARGET)
32
33        # Now create a breakpoint on main.c.
34        breakpoint = target.BreakpointCreateByLocation(self.source, self.line)
35        self.assertTrue(
36            breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT
37        )
38
39        # Now launch the process, and do not stop at the entry point.
40        process = target.LaunchSimple(None, None, self.get_process_working_directory())
41
42        # We should be stopped due to the breakpoint.  Get frame #0.
43        process = target.GetProcess()
44        self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
45        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
46        frame0 = thread.GetFrameAtIndex(0)
47
48        value = frame0.FindValue("g_char_ptr", lldb.eValueTypeVariableGlobal)
49        pointee = value.CreateValueFromAddress(
50            "pointee", value.GetValueAsUnsigned(0), value.GetType().GetPointeeType()
51        )
52        # Watch for write to *g_char_ptr.
53        error = lldb.SBError()
54        wp_opts = lldb.SBWatchpointOptions()
55        wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)
56        watchpoint = target.WatchpointCreateByAddress(
57            value.GetValueAsUnsigned(), 1, wp_opts, error
58        )
59        self.assertTrue(
60            value and watchpoint, "Successfully found the pointer and set a watchpoint"
61        )
62        self.DebugSBValue(value)
63        self.DebugSBValue(pointee)
64
65        # Hide stdout if not running with '-t' option.
66        if not self.TraceOn():
67            self.HideStdout()
68
69        print(watchpoint)
70
71        # Continue.  Expect the program to stop due to the variable being
72        # written to.
73        process.Continue()
74
75        if self.TraceOn():
76            lldbutil.print_stacktraces(process)
77
78        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint)
79        self.assertTrue(thread, "The thread stopped due to watchpoint")
80        self.DebugSBValue(value)
81        self.DebugSBValue(pointee)
82
83        self.expect(
84            lldbutil.print_stacktrace(thread, string_buffer=True),
85            exe=False,
86            substrs=[self.violating_func],
87        )
88
89        # This finishes our test.
90
91    # No size constraint on MIPS for watches
92    @skipIf(archs=["mips", "mipsel", "mips64", "mips64el"])
93    @skipIf(archs=["s390x"])  # Likewise on SystemZ
94    def test_watch_address_with_invalid_watch_size(self):
95        """Exercise SBTarget.WatchpointCreateByAddress() API but pass an invalid watch_size."""
96        self.build()
97        exe = self.getBuildArtifact("a.out")
98
99        # Create a target by the debugger.
100        target = self.dbg.CreateTarget(exe)
101        self.assertTrue(target, VALID_TARGET)
102
103        # Now create a breakpoint on main.c.
104        breakpoint = target.BreakpointCreateByLocation(self.source, self.line)
105        self.assertTrue(
106            breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT
107        )
108
109        # Now launch the process, and do not stop at the entry point.
110        process = target.LaunchSimple(None, None, self.get_process_working_directory())
111
112        # We should be stopped due to the breakpoint.  Get frame #0.
113        process = target.GetProcess()
114        self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
115        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
116        frame0 = thread.GetFrameAtIndex(0)
117
118        value = frame0.FindValue("g_char_ptr", lldb.eValueTypeVariableGlobal)
119        pointee = value.CreateValueFromAddress(
120            "pointee", value.GetValueAsUnsigned(0), value.GetType().GetPointeeType()
121        )
122
123        # debugserver on Darwin AArch64 systems can watch large regions
124        # of memory via https://reviews.llvm.org/D149792 , don't run this
125        # test there.
126        if self.getArchitecture() not in ["arm64", "arm64e", "arm64_32"]:
127            # Watch for write to *g_char_ptr.
128            error = lldb.SBError()
129            wp_opts = lldb.SBWatchpointOptions()
130            wp_opts.SetWatchpointTypeWrite(lldb.eWatchpointWriteTypeOnModify)
131            watchpoint = target.WatchpointCreateByAddress(
132                value.GetValueAsUnsigned(), 365, wp_opts, error
133            )
134            self.assertFalse(watchpoint)
135            self.expect(
136                error.GetCString(),
137                exe=False,
138                substrs=["Setting one of the watchpoint resources failed"],
139            )
140