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