1"""
2Test hardware breakpoints for multiple threads.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12# Hardware breakpoints are supported only by platforms mentioned in oslist.
13@skipUnlessPlatform(oslist=['linux'])
14class HardwareBreakpointMultiThreadTestCase(TestBase):
15    NO_DEBUG_INFO_TESTCASE = True
16
17    mydir = TestBase.compute_mydir(__file__)
18
19    # LLDB supports hardware breakpoints for arm and aarch64 architectures.
20    @skipIf(archs=no_match(['arm', 'aarch64']))
21    def test_hw_break_set_delete_multi_thread(self):
22        self.build()
23        self.setTearDownCleanup()
24        self.break_multi_thread('delete')
25
26    # LLDB supports hardware breakpoints for arm and aarch64 architectures.
27    @skipIf(archs=no_match(['arm', 'aarch64']))
28    def test_hw_break_set_disable_multi_thread(self):
29        self.build()
30        self.setTearDownCleanup()
31        self.break_multi_thread('disable')
32
33    def setUp(self):
34        # Call super's setUp().
35        TestBase.setUp(self)
36        # Our simple source filename.
37        self.source = 'main.cpp'
38        # Find the line number to break inside main().
39        self.first_stop = line_number(
40            self.source, 'Starting thread creation with hardware breakpoint set')
41
42    def break_multi_thread(self, removal_type):
43        """Test that lldb hardware breakpoints work for multiple threads."""
44        self.runCmd("file " + self.getBuildArtifact("a.out"),
45                    CURRENT_EXECUTABLE_SET)
46
47        # Stop in main before creating any threads.
48        lldbutil.run_break_set_by_file_and_line(
49            self, None, self.first_stop, num_expected_locations=1)
50
51        # Run the program.
52        self.runCmd("run", RUN_SUCCEEDED)
53
54        # We should be stopped again due to the breakpoint.
55        # The stop reason of the thread should be breakpoint.
56        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
57                    substrs=['stopped',
58                             'stop reason = breakpoint'])
59
60        # Now set a hardware breakpoint in thread function.
61        self.expect("breakpoint set -b hw_break_function --hardware",
62            substrs=[
63                'Breakpoint',
64                'hw_break_function',
65                'address = 0x'])
66
67        # We should stop in hw_break_function function for 4 threads.
68        count = 0
69
70        while count < 2 :
71
72            self.runCmd("process continue")
73
74            # We should be stopped in hw_break_function
75            # The stop reason of the thread should be breakpoint.
76            self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
77                substrs=[
78                    'stop reason = breakpoint',
79                    'hw_break_function'])
80
81            # Continue the loop and test that we are stopped 4 times.
82            count += 1
83
84        if removal_type == 'delete':
85            self.runCmd("settings set auto-confirm true")
86
87            # Now 'breakpoint delete' should just work fine without confirmation
88            # prompt from the command interpreter.
89            self.expect("breakpoint delete",
90                        startstr="All breakpoints removed")
91
92            # Restore the original setting of auto-confirm.
93            self.runCmd("settings clear auto-confirm")
94
95        elif removal_type == 'disable':
96            self.expect("breakpoint disable",
97                        startstr="All breakpoints disabled.")
98
99        # Continue. Program should exit without stopping anywhere.
100        self.runCmd("process continue")
101
102        # Process should have stopped and exited with status = 0
103        self.expect("process status", PROCESS_STOPPED,
104                    patterns=['Process .* exited with status = 0'])
105