1import gdbremote_testcase
2from lldbsuite.test.decorators import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5
6
7class TestGdbRemoteExpeditedRegisters(
8        gdbremote_testcase.GdbRemoteTestCaseBase):
9
10    mydir = TestBase.compute_mydir(__file__)
11    # <rdar://problem/34539270> lldb-server tests not updated to work on ios etc yet
12    def gather_expedited_registers(self):
13        # Setup the stub and set the gdb remote command stream.
14        procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:2"])
15        self.test_sequence.add_log_lines([
16            # Start up the inferior.
17            "read packet: $c#63",
18            # Immediately tell it to stop.  We want to see what it reports.
19            "read packet: {}".format(chr(3)),
20            {"direction": "send",
21             "regex": r"^\$T([0-9a-fA-F]+)([^#]+)#[0-9a-fA-F]{2}$",
22             "capture": {1: "stop_result",
23                         2: "key_vals_text"}},
24        ], True)
25
26        # Run the gdb remote command stream.
27        context = self.expect_gdbremote_sequence()
28        self.assertIsNotNone(context)
29
30        # Pull out expedited registers.
31        key_vals_text = context.get("key_vals_text")
32        self.assertIsNotNone(key_vals_text)
33
34        expedited_registers = self.extract_registers_from_stop_notification(
35            key_vals_text)
36        self.assertIsNotNone(expedited_registers)
37
38        return expedited_registers
39
40    def stop_notification_contains_generic_register(
41            self, generic_register_name):
42        # Generate a stop reply, parse out expedited registers from stop
43        # notification.
44        expedited_registers = self.gather_expedited_registers()
45        self.assertIsNotNone(expedited_registers)
46        self.assertTrue(len(expedited_registers) > 0)
47
48        # Gather target register infos.
49        reg_infos = self.gather_register_infos()
50
51        # Find the generic register.
52        reg_info = self.find_generic_register_with_name(
53            reg_infos, generic_register_name)
54        self.assertIsNotNone(reg_info)
55
56        # Ensure the expedited registers contained it.
57        self.assertIn(reg_info["lldb_register_index"], expedited_registers)
58        self.trace("{} reg_info:{}".format(generic_register_name, reg_info))
59
60    def test_stop_notification_contains_any_registers(self):
61        self.build()
62        self.set_inferior_startup_launch()
63
64        # Generate a stop reply, parse out expedited registers from stop
65        # notification.
66        expedited_registers = self.gather_expedited_registers()
67        # Verify we have at least one expedited register.
68        self.assertTrue(len(expedited_registers) > 0)
69
70
71    def test_stop_notification_contains_no_duplicate_registers(self):
72        self.build()
73        self.set_inferior_startup_launch()
74
75        # Generate a stop reply, parse out expedited registers from stop
76        # notification.
77        expedited_registers = self.gather_expedited_registers()
78        # Verify no expedited register was specified multiple times.
79        for (reg_num, value) in list(expedited_registers.items()):
80            if (isinstance(value, list)) and (len(value) > 0):
81                self.fail(
82                    "expedited register number {} specified more than once ({} times)".format(
83                        reg_num, len(value)))
84
85    def test_stop_notification_contains_pc_register(self):
86        self.build()
87        self.set_inferior_startup_launch()
88        self.stop_notification_contains_generic_register("pc")
89
90    @skipIf(triple='^powerpc64') # powerpc64 has no FP register
91    def test_stop_notification_contains_fp_register(self):
92        self.build()
93        self.set_inferior_startup_launch()
94        self.stop_notification_contains_generic_register("fp")
95
96    def test_stop_notification_contains_sp_register(self):
97        self.build()
98        self.set_inferior_startup_launch()
99        self.stop_notification_contains_generic_register("sp")
100
101    @skipIf(archs=no_match(["aarch64"]))
102    @skipIf(oslist=no_match(['linux']))
103    def test_stop_notification_contains_vg_register(self):
104        if not self.isAArch64SVE():
105            self.skipTest('SVE registers must be supported.')
106        self.build()
107        self.set_inferior_startup_launch()
108
109        # Generate a stop reply, parse out expedited registers from stop
110        # notification.
111        expedited_registers = self.gather_expedited_registers()
112        self.assertIsNotNone(expedited_registers)
113        self.assertTrue(len(expedited_registers) > 0)
114
115        # Gather target register infos.
116        reg_infos = self.gather_register_infos()
117
118        # Find the vg register.
119        reg_info = self.find_register_with_name_and_dwarf_regnum(
120            reg_infos, 'vg', '46')
121        self.assertIsNotNone(reg_info)
122
123        # Ensure the expedited registers contained it.
124        self.assertIn(reg_info["lldb_register_index"], expedited_registers)
125        self.trace("{} reg_info:{}".format('vg', reg_info))
126