1 # Copyright (C) 2021 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 # Test a binary that uses MTE and exercise various MTE-related scenarios.
21 # Return TAG in hex format with no leading zeroes.
22 proc get_hex_tag { tag } {
23 return [format "%x" $tag]
26 # Return TAG in the NN format where N is 4 bits of the byte.
27 proc get_tag_nn { tag } {
28 return [format "%02x" $tag]
31 # Return the address of PTR with a tag of TAG.
32 proc get_tagged_ptr { tag ptr } {
33 set addr [get_hexadecimal_valueof $ptr -1]
34 return [get_valueof "/x" \
35 "${addr} & (0xf0ffffffffffffff) | ((unsigned long) ${tag} << 56)" \
36 "0" "fetch pointer ${ptr} with tag ${tag}"]
39 # Return the logical TAG from PTR.
40 proc get_ltag_from_ptr { ptr } {
41 set addr [get_hexadecimal_valueof $ptr -1]
42 return [get_valueof "/x" "${addr} >> 56 & 0xf" -1 \
43 "fetch tag from pointer ${ptr}"]
46 if {![is_aarch64_target]} {
47 verbose "Skipping ${gdb_test_file_name}."
52 if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
57 untested "could not run to main"
61 # Targets that don't support memory tagging should not execute the
62 # runtime memory tagging tests.
63 if {![supports_memtag]} {
64 unsupported "memory tagging unsupported"
68 gdb_breakpoint "access_memory"
70 if [gdb_continue "access_memory"] {
74 # Fetch a known pointer to an area mapped with PROT_MTE.
75 set tagged_ptr_symbol "tagged_ptr"
76 set tagged_ptr_addr [get_hexadecimal_valueof $tagged_ptr_symbol -1]
78 if {$tagged_ptr_addr == -1} {
79 unresolved "unexpected pointer or tag value"
83 # Fetch a known pointer to an area not mapped with PROT_MTE.
84 set untagged_ptr_symbol "untagged_ptr"
85 set untagged_ptr_addr [get_hexadecimal_valueof $untagged_ptr_symbol -1]
87 if {$untagged_ptr_addr == -1} {
88 unresolved "unexpected pointer or tag value"
92 with_test_prefix "literals" {
93 # Test inspecting an allocation tag from a pointer to a memory area that
94 # is not mapped with PROT_MTE.
95 set msg "Address ${untagged_ptr_addr} not in a region mapped with a memory tagging flag\."
96 gdb_test "memory-tag print-allocation-tag ${untagged_ptr_addr}" $msg \
97 "memory-tag print-allocation-tag with an untagged address"
99 gdb_test "memory-tag set-allocation-tag ${untagged_ptr_addr} 1 00" $msg \
100 "memory-tag set-allocation-tag with an untagged address"
103 set addr_tagged_valid 0
105 # Test setting and showing the logical tags for a literal address.
106 for {set i 0} {$i < 32} {incr i} {
107 with_test_prefix "tag ${i}" {
108 set addr_tagged [get_tagged_ptr $i ${tagged_ptr_addr}]
111 set tag_hexnz [get_hex_tag [expr $i % 16]]
112 gdb_test "memory-tag print-logical-tag ${addr_tagged}" \
113 " = 0x${tag_hexnz}" \
114 "print-logical-tag with tag ${i}"
116 set tag_hexnn [get_tag_nn $i]
117 gdb_test "memory-tag with-logical-tag ${addr_tagged} ${tag_hexnn}" \
118 " = \\(void \\*\\) ${addr_tagged}" \
119 "with-logical-tag with tag ${i}"
122 set atag_msg "Allocation tag\\(s\\) updated successfully\."
123 # Test setting and showing the allocation tags.
124 for {set i 0} {$i < 32} {incr i} {
126 set tag_hexnn [get_tag_nn $i]
127 gdb_test "memory-tag set-allocation-tag ${tagged_ptr_addr} 1 ${tag_hexnn}" \
129 "set-allocation-tag with tag ${i}"
131 set tag_hexnz [get_hex_tag [expr $i % 16]]
132 gdb_test "memory-tag print-allocation-tag ${tagged_ptr_addr}" " = 0x${tag_hexnz}" \
133 "print-allocation-tag with tag ${i}"
136 # Test tag mismatches.
137 with_test_prefix "tag mismatches" {
138 for {set i 0} {$i < 32} {incr i} {
140 # Set the allocation tag to a known value.
141 set tag_hexnn [get_tag_nn $i]
142 gdb_test "memory-tag set-allocation-tag ${tagged_ptr_addr} 1 ${tag_hexnn}" \
144 "set-allocation-tag with tag ${i}"
146 set atag_hexnz [get_hex_tag [expr $i % 16]]
148 # Validate that the logical tag matches the allocation tag.
149 with_test_prefix "tag ${i}" {
150 set addr_tagged [get_tagged_ptr $i ${tagged_ptr_addr}]
153 gdb_test "memory-tag check ${addr_tagged}" \
154 "Memory tags for address $hex match \\(0x${atag_hexnz}\\)\." \
155 "check match with tag ${i}"
157 # Get a pointer with the logical tag that does not match the
159 set ltag [expr $i + 1]
160 with_test_prefix "fetch mismatch tag ${i}" {
161 set addr_tagged [get_tagged_ptr $ltag ${tagged_ptr_addr}]
164 # Validate that the logical tag does not match the allocation
166 set ltag_hexnz [get_hex_tag [expr [expr $i + 1]% 16]]
167 gdb_test "memory-tag check ${addr_tagged}" \
168 "Logical tag \\(0x${ltag_hexnz}\\) does not match the allocation tag \\(0x${atag_hexnz}\\) for address $hex\." \
169 "check mismatch with tag ${i}"
174 with_test_prefix "symbolic" {
175 # Test inspecting an allocation tag from a pointer to a memory area that
176 # is not mapped with PROT_MTE.
177 set msg "Address ${untagged_ptr_addr} not in a region mapped with a memory tagging flag\."
178 gdb_test "memory-tag print-allocation-tag ${untagged_ptr_symbol}" $msg \
179 "memory-tag print-allocation-tag with an untagged address"
181 gdb_test "memory-tag set-allocation-tag ${untagged_ptr_symbol} 1 00" $msg \
182 "memory-tag set-allocation-tag with an untagged address"
184 # Test setting and showing the logical tags for a literal address.
185 for {set i 0} {$i < 32} {incr i} {
188 with_test_prefix "tag ${i}" {
189 set addr_tagged [get_tagged_ptr $i ${tagged_ptr_addr}]
190 gdb_test_no_output "set variable ${tagged_ptr_symbol} = ${addr_tagged}" \
191 "update value of symbol ${tagged_ptr_symbol}"
194 set tag_hexnz [get_hex_tag [expr $i % 16]]
195 gdb_test "memory-tag print-logical-tag ${tagged_ptr_symbol}" \
196 " = 0x${tag_hexnz}" \
197 "print-logical-tag with tag ${i}"
199 set tag_hexnn [get_tag_nn $i]
200 gdb_test "memory-tag with-logical-tag ${tagged_ptr_symbol} ${tag_hexnn}" \
201 " = \\(void \\*\\) ${addr_tagged}" \
202 "with-logical-tag with tag ${i}"
205 # Reset the tagged ptr to its original value
206 gdb_test_no_output "set variable ${tagged_ptr_symbol} = ${tagged_ptr_addr}" \
207 "reset ${tagged_ptr_symbol} to ${tagged_ptr_addr}"
209 set atag_msg "Allocation tag\\(s\\) updated successfully\."
210 # Test setting and showing the allocation tags.
211 for {set i 0} {$i < 32} {incr i} {
213 set tag_hexnn [get_tag_nn $i]
214 gdb_test "memory-tag set-allocation-tag ${tagged_ptr_symbol} 1 ${tag_hexnn}" \
216 "set-allocation-tag with tag ${i}"
218 set tag_hexnz [get_hex_tag [expr $i % 16]]
219 gdb_test "memory-tag print-allocation-tag ${tagged_ptr_symbol}" \
220 " = 0x${tag_hexnz}" \
221 "print-allocation-tag with tag ${i}"
224 # Test tag mismatches.
225 with_test_prefix "tag mismatches" {
226 for {set i 0} {$i < 32} {incr i} {
228 # Set the allocation tag to a known value (0).
229 set tag_hexnn [get_tag_nn $i]
230 gdb_test "memory-tag set-allocation-tag ${tagged_ptr_symbol} 1 ${tag_hexnn}" \
232 "set-allocation-tag with tag ${i}"
234 set atag_hexnz [get_hex_tag [expr $i % 16]]
236 # Validate that the logical tag matches the allocation tag.
237 with_test_prefix "tag ${i}" {
238 set addr_tagged [get_tagged_ptr $i ${tagged_ptr_addr}]
241 with_test_prefix "tag ${i}" {
242 gdb_test_no_output "set variable ${tagged_ptr_symbol} = ${addr_tagged}" \
243 "set ${tagged_ptr_symbol} to a matching logical tag"
246 gdb_test "memory-tag check ${tagged_ptr_symbol}" \
247 "Memory tags for address $hex match \\(0x${atag_hexnz}\\)\." \
248 "check match with tag ${i}"
250 # Get a pointer with the logical tag that does not match the
252 set ltag [expr $i + 1]
253 with_test_prefix "fetch mismatch tag ${i}" {
254 set addr_tagged [get_tagged_ptr $ltag ${tagged_ptr_addr}]
257 with_test_prefix "tag ${i}" {
258 gdb_test_no_output "set variable ${tagged_ptr_symbol} = ${addr_tagged}" \
259 "set ${tagged_ptr_symbol} to a mismatching logical tag"
262 # Validate that the logical tag does not match the allocation
264 set ltag_hexnz [get_hex_tag [expr [expr $i + 1]% 16]]
265 gdb_test "memory-tag check ${tagged_ptr_symbol}" \
266 "Logical tag \\(0x${ltag_hexnz}\\) does not match the allocation tag \\(0x${atag_hexnz}\\) for address $hex\." \
267 "check mismatch with tag ${i}"
269 # Reset the tagged ptr to its original value
270 gdb_test_no_output "set variable ${tagged_ptr_symbol} = ${tagged_ptr_addr}" \
271 "reset ${tagged_ptr_symbol} to ${tagged_ptr_addr}"
275 # Test the memory tagging extensions for the "print" command.
276 with_test_prefix "print command" {
277 set untagged_ptr [get_tagged_ptr 0 ${tagged_ptr_addr}]
279 with_test_prefix "fetch ltag" {
280 set ltag [get_ltag_from_ptr ${tagged_ptr_addr}]
284 unresolved "unexpected tag value"
288 set atag [expr [expr $ltag + 1] % 16]
289 set atag_hexnn [get_tag_nn $atag]
291 gdb_test "memory-tag set-allocation-tag ${tagged_ptr_symbol} 1 ${atag_hexnn}" \
293 "make atag and ltag different"
295 set atag_hexnz [get_hex_tag $atag]
296 gdb_test "p/x ${tagged_ptr_symbol}" \
298 "Logical tag \\(${ltag}\\) does not match the allocation tag \\(0x${atag_hexnz}\\)\." \
299 "\\\$\[0-9\]+ = ${untagged_ptr}"] \
303 # Test the memory tagging extensions for the "x" command.
304 with_test_prefix "x command" {
306 # Check if the allocation tags match what we expect.
307 gdb_test "x/gxm ${tagged_ptr_symbol}" \
309 "<Allocation Tag $hex for range \\\[$hex,$hex\\)>" \
310 "$hex:\[ \t\]+$hex"] \
311 "outputs tag information"
313 # Also make sure no tag information is output for memory areas without
315 gdb_test "x/gxm ${untagged_ptr_symbol}" \
316 "$hex:\[ \t\]+$hex" \
317 "does not output tag information"
320 # Validate the presence of the MTE registers.
321 foreach reg {"tag_ctl" } {
322 gdb_test "info registers $reg" \
323 "$reg\[ \t\]+$hex\[ \t\]+$decimal" \
324 "register $reg available"
327 # Run until a crash and confirm GDB displays memory tag violation
329 gdb_test "continue" \
331 "Program received signal SIGSEGV, Segmentation fault" \
332 "Memory tag violation while accessing address $hex" \
333 "Allocation tag $hex" \
334 "Logical tag $hex\." \
335 "$hex in access_memory \\(.*\\) at .*" \
336 ".*tagged_ptr\\\[0\\\] = 'a';"] \
337 "display tag violation information"
339 # Restart to execute the async tag fault test.
340 with_test_prefix "async" {
342 untested "could not run to main"
346 gdb_breakpoint "access_memory"
348 if [gdb_continue "access_memory"] {
349 fail "could not run to tagged memory test function"
354 gdb_test "memory-tag set-allocation-tag tagged_ptr 1 05" \
356 "make atag and ltag different"
358 # Force the tag fault to be async.
359 gdb_test_no_output "set \$tag_ctl=0x7fff5" "set tag_ctl to async"
361 # Run until a crash and confirm GDB displays memory tag violation
362 # information for async mode
363 gdb_test "continue" \
365 "Program received signal SIGSEGV, Segmentation fault" \
366 "Memory tag violation" \
367 "Fault address unavailable\." \
368 "$hex in .* \\(.*\\) .*"] \
369 "display tag violation information"