1"""
2Test that "breakpoint set -a" uses the ABI plugin to remove non-address bits
3before attempting to set a breakpoint.
4"""
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class AArch64LinuxNonAddressBitCodeBreak(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    def do_tagged_break(self, hardware):
16        if not self.isAArch64PAuth():
17            self.skipTest("Target must support pointer authentication.")
18
19        self.build()
20        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
21
22        lldbutil.run_break_set_by_file_and_line(
23            self,
24            "main.c",
25            line_number("main.c", "// Set break point at this line."),
26            num_expected_locations=1,
27        )
28
29        self.runCmd("run", RUN_SUCCEEDED)
30
31        if self.process().GetState() == lldb.eStateExited:
32            self.fail("Test program failed to run.")
33
34        self.expect(
35            "thread list",
36            STOPPED_DUE_TO_BREAKPOINT,
37            substrs=["stopped", "stop reason = breakpoint"],
38        )
39
40        cmd = "breakpoint set -a fnptr"
41        # LLDB only has the option to force hardware break, not software.
42        # It prefers sofware break when it can and this will be one of those cases.
43        if hardware:
44            cmd += " --hardware"
45        self.expect(cmd)
46
47        self.runCmd("continue")
48        self.assertEqual(self.process().GetState(), lldb.eStateStopped)
49        self.expect(
50            "thread list",
51            STOPPED_DUE_TO_BREAKPOINT,
52            substrs=["stopped", "`foo at main.c", "stop reason = breakpoint"],
53        )
54
55    # AArch64 Linux always enables the top byte ignore feature
56    @skipUnlessArch("aarch64")
57    @skipUnlessPlatform(["linux"])
58    def test_software_break(self):
59        self.do_tagged_break(False)
60
61    @skipUnlessArch("aarch64")
62    @skipUnlessPlatform(["linux"])
63    def test_hardware_break(self):
64        self.do_tagged_break(True)
65