1"""
2Test watchpoint slots we should not be able to install multiple watchpoints
3within same word boundary. We should be able to install individual watchpoints
4on any of the bytes, half-word, or word. This is only for ARM/AArch64 targets.
5"""
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class WatchpointSlotsTestCase(TestBase):
15    NO_DEBUG_INFO_TESTCASE = True
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20
21        # Source filename.
22        self.source = 'main.c'
23
24        # Output filename.
25        self.exe_name = self.getBuildArtifact("a.out")
26        self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
27
28    # This is a arm and aarch64 specific test case. No other architectures tested.
29    @skipIf(archs=no_match(['arm', 'aarch64']))
30    def test_multiple_watchpoints_on_same_word(self):
31
32        self.build(dictionary=self.d)
33        self.setTearDownCleanup(dictionary=self.d)
34
35        exe = self.getBuildArtifact(self.exe_name)
36        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
37
38        # Detect line number after which we are going to increment arrayName.
39        loc_line = line_number('main.c', '// About to write byteArray')
40
41        # Set a breakpoint on the line detected above.
42        lldbutil.run_break_set_by_file_and_line(
43            self, "main.c", loc_line, num_expected_locations=1, loc_exact=True)
44
45        # Run the program.
46        self.runCmd("run", RUN_SUCCEEDED)
47
48        # The stop reason of the thread should be breakpoint.
49        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
50                     substrs=['stopped', 'stop reason = breakpoint'])
51
52        # Delete breakpoint we just hit.
53        self.expect("breakpoint delete 1", substrs=['1 breakpoints deleted'])
54
55        # Set a watchpoint at byteArray[0]
56        self.expect("watchpoint set variable byteArray[0]", WATCHPOINT_CREATED,
57                    substrs=['Watchpoint created','size = 1'])
58
59        # Use the '-v' option to do verbose listing of the watchpoint.
60        # The hit count should be 0 initially.
61        self.expect("watchpoint list -v 1", substrs=['hit_count = 0'])
62
63        # debugserver on ios doesn't give an error, it creates another watchpoint,
64        # only expect errors on non-darwin platforms.
65        if not self.platformIsDarwin():
66            # Try setting a watchpoint at byteArray[1]
67            self.expect("watchpoint set variable byteArray[1]", error=True,
68                        substrs=['Watchpoint creation failed'])
69
70        self.runCmd("process continue")
71
72        # We should be stopped due to the watchpoint.
73        # The stop reason of the thread should be watchpoint.
74        self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
75                    substrs=['stopped', 'stop reason = watchpoint 1'])
76
77        # Delete the watchpoint we hit above successfully.
78        self.expect("watchpoint delete 1", substrs=['1 watchpoints deleted'])
79
80        # Set a watchpoint at byteArray[3]
81        self.expect("watchpoint set variable byteArray[3]", WATCHPOINT_CREATED,
82                    substrs=['Watchpoint created','size = 1'])
83
84        # Resume inferior.
85        self.runCmd("process continue")
86
87        # We should be stopped due to the watchpoint.
88        # The stop reason of the thread should be watchpoint.
89        if self.platformIsDarwin():
90            # On darwin we'll hit byteArray[3] which is watchpoint 2
91            self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
92                        substrs=['stopped', 'stop reason = watchpoint 2'])
93        else:
94            self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
95                        substrs=['stopped', 'stop reason = watchpoint 3'])
96
97        # Resume inferior.
98        self.runCmd("process continue")
99