diff mbox series

[RFC,9/9] memtag: testsuite: add new tests

Message ID 20241107213937.362703-10-indu.bhagat@oracle.com
State New
Headers show
Series Add -fsanitize=memtag | expand

Commit Message

Indu Bhagat Nov. 7, 2024, 9:39 p.m. UTC
Add basic tests for MEMTAG sanitizer.  MEMTAG sanitizer uses target
hooks to emit AArch64 specific MTE instructions.

Add new target-specific tests.

The currently generated code has quite a few limitations:

1. For basic-1.c testcase, currently we generate:
        subg    x0, x0, #16, #0
        stg     x0, [x0, #0]
        str     w1, [x0]
   The subg can be optimized out. Adding #0 to the tag is
   non-consequential.  The address generation component (x0+16) can be
   folded into the addr operands of stg.

2. Need to generate stgp (pre-index, post-index) above.
   Need to look into how aarch64 backend generates the
   store-pair/load-pair operations currently.  We will likely need to use
   the same framework for generating the store-pair-with-tag (pre-indexed
   and post-indexed) variants for MTE.

3. Also stzp is not generated at all.

TBD:
  - Any suggestions on any of the above 3 will be helpful.
  - Are the tests fittingly placed in gcc.target/aarch64 ? Suggestions
    on other tests are also most welcome.

gcc/testsuite/

	* gcc.target/aarch64/memtag/alloca-1.c: New test.
	* gcc.target/aarch64/memtag/alloca-3.c: New test.
	* gcc.target/aarch64/memtag/arguments-1.c: New test.
	* gcc.target/aarch64/memtag/arguments-2.c: New test.
	* gcc.target/aarch64/memtag/arguments-4.c: New test.
	* gcc.target/aarch64/memtag/arguments.c: New test.
	* gcc.target/aarch64/memtag/basic-1.c: New test.
	* gcc.target/aarch64/memtag/basic-3.c: New test.
	* gcc.target/aarch64/memtag/basic-struct.c: New test.
	* gcc.target/aarch64/memtag/large-array.c: New test.
	* gcc.target/aarch64/memtag/local-no-escape.c: New test.
	* gcc.target/aarch64/memtag/memtag.exp: New test.
	* gcc.target/aarch64/memtag/no-sanitize-attribute.c: New test.
	* gcc.target/aarch64/memtag/vararray-gimple.c: New test.
	* gcc.target/aarch64/memtag/vararray.c: New test.
	* lib/target-supports.exp: Define new proc to detect whether
	AArch64 target supports MTE.
---
 .../gcc.target/aarch64/memtag/alloca-1.c      | 14 ++++++++
 .../gcc.target/aarch64/memtag/alloca-3.c      | 24 ++++++++++++++
 .../gcc.target/aarch64/memtag/arguments-1.c   |  3 ++
 .../gcc.target/aarch64/memtag/arguments-2.c   |  3 ++
 .../gcc.target/aarch64/memtag/arguments-4.c   | 16 ++++++++++
 .../gcc.target/aarch64/memtag/arguments.c     |  3 ++
 .../gcc.target/aarch64/memtag/basic-1.c       | 15 +++++++++
 .../gcc.target/aarch64/memtag/basic-3.c       | 16 ++++++++++
 .../gcc.target/aarch64/memtag/basic-struct.c  | 23 +++++++++++++
 .../gcc.target/aarch64/memtag/large-array.c   | 24 ++++++++++++++
 .../aarch64/memtag/local-no-escape.c          | 20 ++++++++++++
 .../gcc.target/aarch64/memtag/memtag.exp      | 32 +++++++++++++++++++
 .../aarch64/memtag/no-sanitize-attribute.c    | 17 ++++++++++
 .../aarch64/memtag/vararray-gimple.c          | 17 ++++++++++
 .../gcc.target/aarch64/memtag/vararray.c      | 14 ++++++++
 gcc/testsuite/lib/target-supports.exp         | 12 +++++++
 16 files changed, 253 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/alloca-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/alloca-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/arguments-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/arguments-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/arguments-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/arguments.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/basic-struct.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/large-array.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/vararray.c
diff mbox series

Patch

diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/alloca-1.c b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-1.c
new file mode 100644
index 000000000000..76cf2fe64669
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-1.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+
+extern int use (int * b);
+
+int foo (int n)
+{
+  int * b = __builtin_alloca (n);
+  int a = use (b);
+  return a;
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\tstg\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/alloca-3.c b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-3.c
new file mode 100644
index 000000000000..6a336158732a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-3.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+
+extern int use (int * b);
+
+extern int n1;
+extern int n2;
+extern int n3;
+
+int foo (void)
+{
+  int * b1 = __builtin_alloca (n1);
+  int * b2 = __builtin_alloca (n2);
+  int * b3 = __builtin_alloca (n3);
+  int a1 = use (b1);
+  int a2 = use (b2);
+  int a3 = use (b3);
+
+  return a1+a2+a3;
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\taddg\t} 3 } } */
+/* { dg-final { scan-assembler-times {\tstg\t} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/arguments-1.c b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-1.c
new file mode 100644
index 000000000000..8d1e18a761ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-1.c
@@ -0,0 +1,3 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=kernel-hwaddress" } */
+/* { dg-error ".*'-fsanitize=memtag' is incompatible with '-fsanitize=kernel-hwaddress'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/arguments-2.c b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-2.c
new file mode 100644
index 000000000000..7650112dff9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-2.c
@@ -0,0 +1,3 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=kernel-address" } */
+/* { dg-error ".*'-fsanitize=memtag' is incompatible with '-fsanitize=kernel-address'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/arguments-4.c b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-4.c
new file mode 100644
index 000000000000..c5c64bd12454
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-4.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -fno-sanitize=memtag" } */
+
+int use (int * x);
+
+void foo (int n)
+{
+  int x = 99;
+  use (&x);
+}
+
+/* { dg-final { scan-assembler-not "irg" } } */
+/* { dg-final { scan-assembler-not "stg" } } */
+/* { dg-final { scan-assembler-not "st2g" } } */
+/* { dg-final { scan-assembler-not "subg" } } */
+/* { dg-final { scan-assembler-not "addg" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/arguments.c b/gcc/testsuite/gcc.target/aarch64/memtag/arguments.c
new file mode 100644
index 000000000000..83713496c4a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/arguments.c
@@ -0,0 +1,3 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-fsanitize=address" } */
+/* { dg-error ".*'-fsanitize=memtag' is incompatible with '-fsanitize=address'.*" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c b/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c
new file mode 100644
index 000000000000..b76f27d5e553
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+/* FIXME - scan-assembler-times-not subg ?  */
+/* FIXME - generate stgp instead of stg + str ?  */
+
+int use (int * x);
+
+void foo (int n)
+{
+  int x = 99;
+  use (&x);
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\tstg\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c b/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c
new file mode 100644
index 000000000000..a54437951154
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+
+int use (int * x);
+
+void foo (int n)
+{
+ int a, b, c;
+ use(&a);
+ use(&b);
+ use(&c);
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\tstg\t} 3 } } */
+/* { dg-final { scan-assembler-times {\tst2g\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/basic-struct.c b/gcc/testsuite/gcc.target/aarch64/memtag/basic-struct.c
new file mode 100644
index 000000000000..7751d109371e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-struct.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+/* FIXME - scan-assembler-times stz2p ?  */
+
+struct A
+{
+  long a;
+  long b;
+  long c;
+  long d;
+};
+
+extern void use (struct A *a);
+
+long f (void)
+{
+  struct A a = {0, 0, 64, (long)&a};
+  use (&a);
+  return a.b;
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\tst2g\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c b/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c
new file mode 100644
index 000000000000..b5b944f4633b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+/* FIXME - add other checks later. For now make sure this does not ICE.  */
+
+#define ARRAY_LEN 12000
+
+int create (void);
+
+void sort (int *data, int n);
+
+void sort_array()
+{
+  int data[ARRAY_LEN], i;
+
+  for (i=0; i<ARRAY_LEN; ++i)
+    {
+      data[i] = create ();
+    }
+  
+  sort(data, ARRAY_LEN);
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\tst2g\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c b/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c
new file mode 100644
index 000000000000..173fe1135bf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O0" } */
+
+/* FIXME - If x doesnt escape the function, why should MTE tagging be done for
+   x ?  */
+
+extern int use (int *x);
+extern int bar (int *x);
+extern int baz (int *x);
+
+int a[10];
+
+int foo (int n)
+{
+  int x = use (a);
+  if (x)
+    return bar (a);
+  else
+    return baz (a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp b/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp
new file mode 100644
index 000000000000..7f45fa99835d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp
@@ -0,0 +1,32 @@ 
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+if [check_effective_target_aarch64_mte] {
+  dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+	"" "-fsanitize=memtag -march=armv8.5-a+memtag"
+}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c b/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c
new file mode 100644
index 000000000000..39d1d432384e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+
+int use (int * x);
+
+__attribute__((no_sanitize("memtag")))
+void foo (int n)
+{
+  int x = 99;
+  use (&x);
+}
+
+/* { dg-final { scan-assembler-not "irg" } } */
+/* { dg-final { scan-assembler-not "stg" } } */
+/* { dg-final { scan-assembler-not "st2g" } } */
+/* { dg-final { scan-assembler-not "subg" } } */
+/* { dg-final { scan-assembler-not "addg" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c b/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c
new file mode 100644
index 000000000000..f270ac619137
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-asan -O2" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+extern int *use (int *b, int n);
+
+int* foo (int n)
+{
+  int b[n];
+  return use (b, n);
+}
+
+/* HWASAN_ALLOCA_POISON is used for alloca and VLAs when MEMTAG is in effect.
+   Although HWASAN_ALLOCA_UNPOISON is (also) used for untagging frame, it
+   doesnt hurt to check it in context of the current test.  */
+/* { dg-final { scan-tree-dump "HWASAN_ALLOCA_POISON" "asan1" } } */
+/* { dg-final { scan-tree-dump "HWASAN_ALLOCA_UNPOISON" "asan1" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/vararray.c b/gcc/testsuite/gcc.target/aarch64/memtag/vararray.c
new file mode 100644
index 000000000000..ce115dc231b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/memtag/vararray.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+/* FIXME - scan-assembler-times-not addg ?  */
+
+extern int *use (int *b, int n);
+
+int* foo (int n)
+{
+  int b[n];
+  return use (b, n);
+}
+
+/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
+/* { dg-final { scan-assembler-times {\tstg\t} 3 } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 75703ddca608..87c2d50bc553 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -4698,6 +4698,18 @@  proc check_effective_target_aarch64_sve1_only { } {
 		   && ![check_effective_target_aarch64_sve2] }]
 }
 
+# Return 1 if this is an AArch64 target supporting MTE.
+# FIXME what is aarch64_mte.  more stubs needed ?
+proc check_effective_target_aarch64_mte { } {
+    if { ![istarget aarch64*-*-*] } {
+	return 0
+    }
+    return [check_no_compiler_messages aarch64_mte assembly {
+	#if !defined (__ARM_FEATURE_MEMORY_TAGGING)
+	#error FOO
+	#endif
+    } "-march=armv8.5-a+memtag"]
+}
 # Return the size in bits of an SVE vector, or 0 if the size is variable.
 proc aarch64_sve_bits { } {
     return [check_cached_effective_target aarch64_sve_bits {