xref: /llvm-project/lldb/test/API/tools/lldb-server/register-reading/TestGdbRemoteGPacket.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1import gdbremote_testcase
2import textwrap
3from lldbsuite.test.decorators import *
4from lldbsuite.test.lldbtest import *
5from lldbsuite.test import lldbutil
6
7
8def _extract_register_value(reg_info, reg_bank, byte_order, bytes_per_entry=8):
9    reg_offset = int(reg_info["offset"]) * 2
10    reg_byte_size = int(2 * int(reg_info["bitsize"]) / 8)
11    # Create slice with the contents of the register.
12    reg_slice = reg_bank[reg_offset : reg_offset + reg_byte_size]
13
14    reg_value = []
15    # Wrap slice according to bytes_per_entry.
16    for entry in textwrap.wrap(reg_slice, 2 * bytes_per_entry):
17        # Invert the bytes order if target uses little-endian.
18        if byte_order == lldb.eByteOrderLittle:
19            entry = "".join(
20                reversed([entry[i : i + 2] for i in range(0, len(entry), 2)])
21            )
22        reg_value.append("0x" + entry)
23
24    return reg_value
25
26
27class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase):
28    @skipIfOutOfTreeDebugserver
29    @skipUnlessDarwin  # G packet not supported
30    def test_g_packet(self):
31        self.build()
32        self.prep_debug_monitor_and_inferior()
33        self.test_sequence.add_log_lines(
34            [
35                "read packet: $g#67",
36                {
37                    "direction": "send",
38                    "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
39                    "capture": {1: "register_bank"},
40                },
41            ],
42            True,
43        )
44        context = self.expect_gdbremote_sequence()
45        register_bank = context.get("register_bank")
46        self.assertNotEqual(register_bank[0], "E")
47
48        self.test_sequence.add_log_lines(
49            [
50                "read packet: $G" + register_bank + "#00",
51                {
52                    "direction": "send",
53                    "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
54                    "capture": {1: "G_reply"},
55                },
56            ],
57            True,
58        )
59        context = self.expect_gdbremote_sequence()
60        self.assertNotEqual(context.get("G_reply")[0], "E")
61
62    @skipIf(archs=no_match(["x86_64"]))
63    def g_returns_correct_data(self, with_suffix):
64        procs = self.prep_debug_monitor_and_inferior()
65
66        self.add_register_info_collection_packets()
67        if with_suffix:
68            self.add_thread_suffix_request_packets()
69        self.add_threadinfo_collection_packets()
70        context = self.expect_gdbremote_sequence()
71        self.assertIsNotNone(context)
72
73        # Gather register info.
74        reg_infos = self.parse_register_info_packets(context)
75        self.assertIsNotNone(reg_infos)
76        self.add_lldb_register_index(reg_infos)
77        # Index register info entries by name.
78        reg_infos = {info["name"]: info for info in reg_infos}
79
80        # Gather thread info.
81        if with_suffix:
82            threads = self.parse_threadinfo_packets(context)
83            self.assertIsNotNone(threads)
84            thread_id = threads[0]
85            self.assertIsNotNone(thread_id)
86        else:
87            thread_id = None
88
89        # Send vCont packet to resume the inferior.
90        self.test_sequence.add_log_lines(
91            [
92                "read packet: $vCont;c#a8",
93                {
94                    "direction": "send",
95                    "regex": r"^\$T([0-9a-fA-F]{2}).*#[0-9a-fA-F]{2}$",
96                    "capture": {1: "hex_exit_code"},
97                },
98            ],
99            True,
100        )
101
102        # Send g packet to retrieve the register bank
103        if thread_id:
104            g_request = "read packet: $g;thread:{:x}#00".format(thread_id)
105        else:
106            g_request = "read packet: $g#00"
107        self.test_sequence.add_log_lines(
108            [
109                g_request,
110                {
111                    "direction": "send",
112                    "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
113                    "capture": {1: "register_bank"},
114                },
115            ],
116            True,
117        )
118        context = self.expect_gdbremote_sequence()
119        self.assertIsNotNone(context)
120        reg_bank = context.get("register_bank")
121        self.assertNotEqual(reg_bank[0], "E")
122
123        byte_order = self.get_target_byte_order()
124        get_reg_value = lambda reg_name: _extract_register_value(
125            reg_infos[reg_name], reg_bank, byte_order
126        )
127
128        self.assertEqual(["0x0102030405060708"], get_reg_value("r8"))
129        self.assertEqual(["0x1112131415161718"], get_reg_value("r9"))
130        self.assertEqual(["0x2122232425262728"], get_reg_value("r10"))
131        self.assertEqual(["0x3132333435363738"], get_reg_value("r11"))
132        self.assertEqual(["0x4142434445464748"], get_reg_value("r12"))
133        self.assertEqual(["0x5152535455565758"], get_reg_value("r13"))
134        self.assertEqual(["0x6162636465666768"], get_reg_value("r14"))
135        self.assertEqual(["0x7172737475767778"], get_reg_value("r15"))
136
137        self.assertEqual(
138            ["0x020406080a0c0e01", "0x030507090b0d0f00"], get_reg_value("xmm8")
139        )
140        self.assertEqual(
141            ["0x121416181a1c1e11", "0x131517191b1d1f10"], get_reg_value("xmm9")
142        )
143        self.assertEqual(
144            ["0x222426282a2c2e21", "0x232527292b2d2f20"], get_reg_value("xmm10")
145        )
146        self.assertEqual(
147            ["0x323436383a3c3e31", "0x333537393b3d3f30"], get_reg_value("xmm11")
148        )
149        self.assertEqual(
150            ["0x424446484a4c4e41", "0x434547494b4d4f40"], get_reg_value("xmm12")
151        )
152        self.assertEqual(
153            ["0x525456585a5c5e51", "0x535557595b5d5f50"], get_reg_value("xmm13")
154        )
155        self.assertEqual(
156            ["0x626466686a6c6e61", "0x636567696b6d6f60"], get_reg_value("xmm14")
157        )
158        self.assertEqual(
159            ["0x727476787a7c7e71", "0x737577797b7d7f70"], get_reg_value("xmm15")
160        )
161
162    @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48420")
163    @expectedFailureNetBSD
164    @skipIfDarwin  # g packet not supported
165    def test_g_returns_correct_data_with_suffix(self):
166        self.build()
167        self.set_inferior_startup_launch()
168        self.g_returns_correct_data(True)
169
170    @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48420")
171    @expectedFailureNetBSD
172    @skipIfDarwin  # g packet not supported
173    def test_g_returns_correct_data_no_suffix(self):
174        self.build()
175        self.set_inferior_startup_launch()
176        self.g_returns_correct_data(False)
177