xref: /qemu/tests/tcg/aarch64/gdbstub/test-mte.py (revision e087bd4de3369d678ed8ebda4ba1c11b782cf899)
1 from __future__ import print_function
2 #
3 # Test GDB memory-tag commands that exercise the stubs for the qIsAddressTagged,
4 # qMemTag, and QMemTag packets, which are used for manipulating allocation tags.
5 # Logical tags-related commands rely on local operations, hence don't exercise
6 # any stub and so are not used in this test.
7 #
8 # The test consists in breaking just after a tag is set in a specific memory
9 # chunk, and then using the GDB 'memory-tagging' subcommands to set/get tags in
10 # different memory locations and ranges in the MTE-enabled memory chunk.
11 #
12 # This is launched via tests/guest-debug/run-test.py
13 #
14 
15 
16 try:
17     import gdb
18 except ModuleNotFoundError:
19     from sys import exit
20     exit("This script must be launched via tests/guest-debug/run-test.py!")
21 import re
22 from sys import argv
23 from test_gdbstub import arg_parser, main, report
24 
25 
26 PATTERN_0 = r"Memory tags for address 0x[0-9a-f]+ match \(0x[0-9a-f]+\)."
27 PATTERN_1 = r".*(0x[0-9a-f]+)"
28 
29 
30 def run_test():
31     p = arg_parser(prog="test-mte.py", description="TCG MTE tests.")
32     p.add_argument("--mode", help="Run test for QEMU system or user mode.",
33                    required=True, choices=['system','user'])
34 
35     args = p.parse_args(args=argv)
36 
37     if args.mode == "system":
38         # Break address: where to break before performing the tests
39         # See mte.S for details about this label.
40         ba = "main_end"
41         # Tagged address: the start of the MTE-enabled memory chunk to be tested
42         # 'tagged_addr' (x1) is a pointer to the MTE-enabled page. See mte.S.
43         ta = "$x1"
44     else: # mode="user"
45         # Line 95 in mte-8.c
46         ba = "95"
47         # 'a' array. See mte-8.c
48         ta = "a"
49 
50     gdb.execute(f"break {ba}", False, True)
51     gdb.execute("continue", False, True)
52 
53     try:
54         # Test if we can check correctly that the allocation tag for the address
55         # in {ta} matches the logical tag in {ta}.
56         co = gdb.execute(f"memory-tag check {ta}", False, True)
57         tags_match = re.findall(PATTERN_0, co, re.MULTILINE)
58         if tags_match:
59             report(True, f"{tags_match[0]}")
60         else:
61             report(False, "Logical and allocation tags don't match!")
62 
63         # Test allocation tag 'set and print' commands. Commands on logical
64         # tags rely on local operation and so don't exercise any stub.
65 
66         # Set the allocation tag for the first granule (16 bytes) of
67         # address starting at {ta} address to a known value, i.e. 0x04.
68         gdb.execute(f"memory-tag set-allocation-tag {ta} 1 04", False, True)
69 
70         # Then set the allocation tag for the second granule to a known
71         # value, i.e. 0x06. This tests that contiguous tag granules are
72         # set correctly and don't run over each other.
73         gdb.execute(f"memory-tag set-allocation-tag {ta}+16 1 06", False, True)
74 
75         # Read the known values back and check if they remain the same.
76 
77         co = gdb.execute(f"memory-tag print-allocation-tag {ta}", False, True)
78         first_tag = re.match(PATTERN_1, co)[1]
79 
80         co = gdb.execute(f"memory-tag print-allocation-tag {ta}+16", False, True)
81         second_tag = re.match(PATTERN_1, co)[1]
82 
83         if first_tag == "0x4" and second_tag == "0x6":
84             report(True, "Allocation tags are correctly set/printed.")
85         else:
86             report(False, "Can't set/print allocation tags!")
87 
88         # Now test fill pattern by setting a whole page with a pattern.
89         gdb.execute(f"memory-tag set-allocation-tag {ta} 4096 0a0b", False, True)
90 
91         # And read back the tags of the last two granules in page so
92         # we also test if the pattern is set correctly up to the end of
93         # the page.
94         co = gdb.execute(f"memory-tag print-allocation-tag {ta}+4096-32", False, True)
95         tag = re.match(PATTERN_1, co)[1]
96 
97         co = gdb.execute(f"memory-tag print-allocation-tag {ta}+4096-16", False, True)
98         last_tag = re.match(PATTERN_1, co)[1]
99 
100         if tag == "0xa" and last_tag == "0xb":
101             report(True, "Fill pattern is ok.")
102         else:
103             report(False, "Fill pattern failed!")
104 
105     except gdb.error:
106         # This usually happens because a GDB version that does not support
107         # memory tagging was used to run the test.
108         report(False, "'memory-tag' command failed!")
109 
110 
111 main(run_test, expected_arch="aarch64")
112