1import gdbremote_testcase
2from lldbsuite.test.decorators import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5
6"""
7Check that lldb-server correctly processes qMemTags and QMemTags packets.
8
9In the tests below E03 means the packet wasn't formed correctly
10and E01 means it was but we had some other error acting upon it.
11
12We do not test reading or writing over a page boundary
13within the same mapping. That logic is handled in the kernel
14so it's just a single ptrace call for lldb-server.
15"""
16
17class TestGdbRemoteMemoryTagging(gdbremote_testcase.GdbRemoteTestCaseBase):
18
19    def check_memtags_response(self, packet_name, body, expected):
20        self.test_sequence.add_log_lines(["read packet: ${}:{}#00".format(packet_name, body),
21                                          "send packet: ${}#00".format(expected),
22                                          ],
23                                         True)
24        self.expect_gdbremote_sequence()
25
26    def check_tag_read(self, body, expected):
27        self.check_memtags_response("qMemTags", body, expected)
28
29    def prep_memtags_test(self):
30        self.build()
31        self.set_inferior_startup_launch()
32        procs = self.prep_debug_monitor_and_inferior()
33
34        # We don't use isAArch64MTE here because we cannot do runCmd in an
35        # lldb-server test. Instead we run the example and skip if it fails
36        # to allocate an MTE buffer.
37
38        # Run the process
39        self.test_sequence.add_log_lines(
40            [
41                # Start running after initial stop
42                "read packet: $c#63",
43		# Match the address of the MTE page
44                {"type": "output_match",
45                 "regex": self.maybe_strict_output_regex(r"buffer: (.+) page_size: (.+)\r\n"),
46                 "capture": {1: "buffer", 2: "page_size"}},
47                # Now stop the inferior
48                "read packet: {}".format(chr(3)),
49                # And wait for the stop notification
50                {"direction": "send", "regex": r"^\$T[0-9a-fA-F]{2}thread:[0-9a-fA-F]+;"}],
51            True)
52
53        # Run the packet stream
54        context = self.expect_gdbremote_sequence()
55        self.assertIsNotNone(context)
56
57        buf_address = context.get("buffer")
58        self.assertIsNotNone(buf_address)
59        page_size = context.get("page_size")
60        self.assertIsNotNone(page_size)
61
62        # nil means we couldn't set up a tagged page because the
63        # target doesn't support it.
64        if buf_address == "(nil)":
65            self.skipTest("Target must support MTE.")
66
67        buf_address = int(buf_address, 16)
68        page_size = int(page_size, 16)
69
70        return buf_address, page_size
71
72    @skipUnlessArch("aarch64")
73    @skipUnlessPlatform(["linux"])
74    @skipUnlessAArch64MTELinuxCompiler
75    def test_qMemTags_packets(self):
76        """ Test that qMemTags packets are parsed correctly and/or rejected. """
77        buf_address, page_size = self.prep_memtags_test()
78
79        # Sanity check that address is correct
80        self.check_tag_read("{:x},20:1".format(buf_address), "m0001")
81
82        # Invalid packets
83
84        # No content
85        self.check_tag_read("", "E03")
86        # Only address
87        self.check_tag_read("{:x}".format(buf_address), "E03")
88        # Only address and length
89        self.check_tag_read("{:x},20".format(buf_address), "E03")
90        # Empty address
91        self.check_tag_read(",20:1", "E03")
92        # Invalid addresses
93        self.check_tag_read("aardvark,20:1", "E03")
94        self.check_tag_read("-100,20:1", "E03")
95        self.check_tag_read("cafe?,20:1", "E03")
96        # Empty length
97        self.check_tag_read("{:x},:1".format(buf_address), "E03")
98        # Invalid lengths
99        self.check_tag_read("{:x},food:1".format(buf_address), "E03")
100        self.check_tag_read("{:x},-1:1".format(buf_address), "E03")
101        self.check_tag_read("{:x},12??:1".format(buf_address), "E03")
102        # Empty type
103        self.check_tag_read("{:x},10:".format(buf_address), "E03")
104        # Types we don't support
105        self.check_tag_read("{:x},10:FF".format(buf_address), "E01")
106        # Types can also be negative, -1 in this case.
107        # So this is E01 for not supported, instead of E03 for invalid formatting.
108        self.check_tag_read("{:x},10:FFFFFFFF".format(buf_address), "E01")
109        # (even if the length of the read is zero)
110        self.check_tag_read("{:x},0:FF".format(buf_address), "E01")
111        # Invalid type format
112        self.check_tag_read("{:x},10:cat".format(buf_address), "E03")
113        self.check_tag_read("{:x},10:?11".format(buf_address), "E03")
114        # Type is signed but in packet as raw bytes, no +/-.
115        self.check_tag_read("{:x},10:-1".format(buf_address), "E03")
116        self.check_tag_read("{:x},10:+20".format(buf_address), "E03")
117        # We do use a uint64_t for unpacking but that's just an implementation
118        # detail. Any value > 32 bit is invalid.
119        self.check_tag_read("{:x},10:123412341".format(buf_address), "E03")
120
121        # Valid packets
122
123        # Reading nothing is allowed
124        self.check_tag_read("{:x},0:1".format(buf_address), "m")
125        # A range that's already aligned
126        self.check_tag_read("{:x},20:1".format(buf_address), "m0001")
127        # lldb-server should re-align the range
128        # Here we read from 1/2 way through a granule, into the next. Expands to 2 granules
129        self.check_tag_read("{:x},10:1".format(buf_address+64-8), "m0304")
130        # Read up to the end of an MTE page.
131        # We know that the last tag should be 0xF since page size will always be a
132        # multiple of 256 bytes, which is 16 granules and we have 16 tags to use.
133        self.check_tag_read("{:x},10:1".format(buf_address+page_size-16), "m0f")
134        # Here we read off of the end of the MTE range so ptrace gives us one tag,
135        # then fails on the second call. To lldb-server this means the response
136        # should just be an error, not a partial read.
137        self.check_tag_read("{:x},20:1".format(buf_address+page_size-16), "E01")
138
139    def check_tag_write(self, body, expected):
140        self.check_memtags_response("QMemTags", body, expected)
141
142    @skipUnlessArch("aarch64")
143    @skipUnlessPlatform(["linux"])
144    @skipUnlessAArch64MTELinuxCompiler
145    def test_QMemTags_packets(self):
146        """ Test that QMemTags packets are parsed correctly and/or rejected. """
147        buf_address, page_size = self.prep_memtags_test()
148
149        # Sanity check that address is correct
150        self.check_tag_write("{:x},10:1:0e".format(buf_address), "OK")
151        self.check_tag_read("{:x},10:1".format(buf_address), "m0e")
152
153        # No content
154        self.check_tag_write("", "E03")
155        # Only address
156        self.check_tag_write("{:x}".format(buf_address), "E03")
157        # Only address and length
158        self.check_tag_write("{:x},20".format(buf_address), "E03")
159        # Missing data
160        self.check_tag_write("{:x},20:1".format(buf_address), "E03")
161        # Zero length write must still include seperator after type
162        self.check_tag_write("{:x},0:1".format(buf_address), "E03")
163        # Empty address
164        self.check_tag_write(",10:1:01", "E03")
165        # Invalid addresses
166        self.check_tag_write("aardvark,10:1:01", "E03")
167        self.check_tag_write("-100,10:1:01", "E03")
168        self.check_tag_write("cafe?,10:1:01", "E03")
169        # Empty length
170        self.check_tag_write("{:x},:1:01".format(buf_address), "E03")
171        # Invalid lengths
172        self.check_tag_write("{:x},food:1:01".format(buf_address), "E03")
173        self.check_tag_write("{:x},-1:1:01".format(buf_address), "E03")
174        self.check_tag_write("{:x},12??:1:01".format(buf_address), "E03")
175        # Empty type
176        self.check_tag_write("{:x},10::01".format(buf_address), "E03")
177        # Types we don't support
178        self.check_tag_write("{:x},10:FF:01".format(buf_address), "E01")
179        # (even if the length of the write is zero)
180        self.check_tag_write("{:x},0:FF:".format(buf_address), "E01")
181        # Invalid type format
182        self.check_tag_write("{:x},0:cat:".format(buf_address), "E03")
183        self.check_tag_write("{:x},0:?11:".format(buf_address), "E03")
184        # Leading +/- not allowed
185        self.check_tag_write("{:x},10:-1:".format(buf_address), "E03")
186        self.check_tag_write("{:x},10:+20:".format(buf_address), "E03")
187        # We use a uint64_t when parsing, but dont expect anything > 32 bits
188        self.check_tag_write("{:x},10:123412341:".format(buf_address), "E03")
189        # Invalid tag data
190        self.check_tag_write("{:x},10:1:??".format(buf_address), "E03")
191        self.check_tag_write("{:x},10:1:45?".format(buf_address), "E03")
192        # (must be 2 chars per byte)
193        self.check_tag_write("{:x},10:1:123".format(buf_address), "E03")
194        # Tag out of range
195        self.check_tag_write("{:x},10:1:23".format(buf_address), "E01")
196        # Non-zero length write must include some tag data
197        self.check_tag_write("{:x},10:1:".format(buf_address), "E01")
198
199        # Valid packets
200
201        # Zero length write doesn't need any tag data (but should include the :)
202        self.check_tag_write("{:x},0:1:".format(buf_address), "OK")
203        # Zero length unaligned is the same
204        self.check_tag_write("{:x},0:1:".format(buf_address+8), "OK")
205        # Ranges can be aligned already
206        self.check_tag_write("{:x},20:1:0405".format(buf_address), "OK")
207        self.check_tag_read("{:x},20:1".format(buf_address), "m0405")
208        # Unaliged ranges will be aligned by the server
209        self.check_tag_write("{:x},10:1:0607".format(buf_address+8), "OK")
210        self.check_tag_read("{:x},20:1".format(buf_address), "m0607")
211        # Tags will be repeated as needed to cover the range
212        self.check_tag_write("{:x},30:1:09".format(buf_address), "OK")
213        self.check_tag_read("{:x},30:1".format(buf_address), "m090909")
214        # One more repeating tags for good measure, part repetition this time
215        # (for full tests see the MemoryTagManagerAArch64MTE unittests)
216        self.check_tag_write("{:x},30:1:0a0b".format(buf_address), "OK")
217        self.check_tag_read("{:x},30:1".format(buf_address), "m0a0b0a")
218        # We can write up to the end of the MTE page
219        last_granule = buf_address + page_size - 16;
220        self.check_tag_write("{:x},10:1:0c".format(last_granule), "OK")
221        self.check_tag_read("{:x},10:1".format(last_granule), "m0c")
222        # Writing over the end of the page is an error
223        self.check_tag_write("{:x},20:1:0d".format(last_granule), "E01")
224        # The last tag in the page was written thought, and we do not
225        # attempt to restore its original value.
226        self.check_tag_read("{:x},10:1".format(last_granule), "m0d")
227