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