1"""
2Test lldb watchpoint that uses 'watchpoint set -w write -s size' to watch a pointed location with size.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class WatchLocationUsingWatchpointSetTestCase(TestBase):
14
15    mydir = TestBase.compute_mydir(__file__)
16    NO_DEBUG_INFO_TESTCASE = True
17
18    def setUp(self):
19        # Call super's setUp().
20        TestBase.setUp(self)
21        # Our simple source filename.
22        self.source = 'main.cpp'
23        # Find the line number to break inside main().
24        self.line = line_number(
25            self.source, '// Set break point at this line.')
26        # This is for verifying that watch location works.
27        self.violating_func = "do_bad_thing_with_location"
28        # Build dictionary to have unique executable names for each test
29        # method.
30
31    @skipIf(
32        oslist=["linux"],
33        archs=[
34            'aarch64',
35            'arm'],
36        bugnumber="llvm.org/pr26031")
37    def test_watchlocation_using_watchpoint_set(self):
38        """Test watching a location with 'watchpoint set expression -w write -s size' option."""
39        self.build()
40        self.setTearDownCleanup()
41
42        exe = self.getBuildArtifact("a.out")
43        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
44
45        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
46        lldbutil.run_break_set_by_file_and_line(
47            self, None, self.line, num_expected_locations=1)
48
49        # Run the program.
50        self.runCmd("run", RUN_SUCCEEDED)
51
52        # We should be stopped again due to the breakpoint.
53        # The stop reason of the thread should be breakpoint.
54        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
55                    substrs=['stopped',
56                             'stop reason = breakpoint'])
57
58        # Now let's set a write-type watchpoint pointed to by 'g_char_ptr' and
59        # with offset as 7.
60        # The main.cpp, by design, misbehaves by not following the agreed upon
61        # protocol of only accessing the allowable index range of [0, 6].
62        self.expect(
63            "watchpoint set expression -w write -s 1 -- g_char_ptr + 7",
64            WATCHPOINT_CREATED,
65            substrs=[
66                'Watchpoint created',
67                'size = 1',
68                'type = w'])
69        self.runCmd("expr unsigned val = g_char_ptr[7]; val")
70        self.expect(self.res.GetOutput().splitlines()[0], exe=False,
71                    endstr=' = 0')
72
73        # Use the '-v' option to do verbose listing of the watchpoint.
74        # The hit count should be 0 initially.
75        self.expect("watchpoint list -v",
76                    substrs=['hit_count = 0'])
77
78        self.runCmd("process continue")
79
80        # We should be stopped again due to the watchpoint (write type), but
81        # only once.  The stop reason of the thread should be watchpoint.
82        self.expect(
83            "thread list",
84            STOPPED_DUE_TO_WATCHPOINT,
85            substrs=[
86                'stopped',
87                self.violating_func,
88                'stop reason = watchpoint',
89            ])
90
91        # Switch to the thread stopped due to watchpoint and issue some
92        # commands.
93        self.switch_to_thread_with_stop_reason(lldb.eStopReasonWatchpoint)
94        self.runCmd("thread backtrace")
95        self.runCmd("expr unsigned val = g_char_ptr[7]; val")
96        self.expect(self.res.GetOutput().splitlines()[0], exe=False,
97                    endstr=' = 99')
98
99        # Use the '-v' option to do verbose listing of the watchpoint.
100        # The hit count should now be the same as the number of threads that
101        # stopped on a watchpoint.
102        threads = lldbutil.get_stopped_threads(
103            self.process(), lldb.eStopReasonWatchpoint)
104        self.expect("watchpoint list -v",
105                    substrs=['hit_count = %d' % len(threads)])
106
107        self.runCmd("thread backtrace all")
108