Hi Claudiu, > -----Original Message----- > From: [email protected] <claudiu.zissulescu- > [email protected]> > Sent: 09 December 2025 10:58 > To: [email protected] > Cc: [email protected]; [email protected]; Tamar Christina > <[email protected]>; Wilco Dijkstra <[email protected]> > Subject: [PATCH 2/2] aarch64: Add memtag-stack tests > > From: Claudiu Zissulescu <[email protected]> > > Add basic tests for memtag-stack sanitizer. Memtag stack sanitizer > uses target hooks to emit AArch64 specific MTE instructions. > > gcc/testsuite: > > * lib/target-supports.exp:
Empty block > * gcc.target/aarch64/memtag/alloca-1.c: New test. > * gcc.target/aarch64/memtag/alloca-2.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-3.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 file. > * gcc.target/aarch64/memtag/no-sanitize-attribute.c: New test. > * gcc.target/aarch64/memtag/value-init.c: New test. > * gcc.target/aarch64/memtag/vararray-gimple.c: New test. > * gcc.target/aarch64/memtag/vararray.c: New test. > * gcc.target/aarch64/memtag/zero-init.c: New test. > * gcc.target/aarch64/memtag/texec-1.c: New test. > * gcc.target/aarch64/memtag/texec-2.c: New test. > * gcc.target/aarch64/memtag/texec-3.c: New test. > * gcc.target/aarch64/memtag/vla-1.c: New test. > * gcc.target/aarch64/memtag/vla-2.c: New test. > * testsuite/lib/target-supports.exp > (check_effective_target_aarch64_mte): New funcction. > > Co-authored-by: Indu Bhagat <[email protected]> > Signed-off-by: Claudiu Zissulescu <[email protected]> Patch is OK but please update the copyright year in memtag.exp. Thanks, Tamar > --- > .../gcc.target/aarch64/memtag/alloca-1.c | 15 ++++++ > .../gcc.target/aarch64/memtag/alloca-2.c | 15 ++++++ > .../gcc.target/aarch64/memtag/alloca-3.c | 28 +++++++++++ > .../gcc.target/aarch64/memtag/arguments-1.c | 3 ++ > .../gcc.target/aarch64/memtag/arguments-2.c | 3 ++ > .../gcc.target/aarch64/memtag/arguments-3.c | 3 ++ > .../gcc.target/aarch64/memtag/arguments-4.c | 16 +++++++ > .../gcc.target/aarch64/memtag/arguments.c | 3 ++ > .../gcc.target/aarch64/memtag/basic-1.c | 14 ++++++ > .../gcc.target/aarch64/memtag/basic-3.c | 28 +++++++++++ > .../gcc.target/aarch64/memtag/basic-struct.c | 22 +++++++++ > .../aarch64/memtag/cfi-mte-memtag-frame-1.c | 11 +++++ > .../gcc.target/aarch64/memtag/large-array.c | 23 +++++++++ > .../aarch64/memtag/local-no-escape.c | 22 +++++++++ > .../gcc.target/aarch64/memtag/memtag.exp | 32 +++++++++++++ > .../gcc.target/aarch64/memtag/mte-sig.h | 15 ++++++ > .../aarch64/memtag/no-sanitize-attribute.c | 18 +++++++ > .../gcc.target/aarch64/memtag/texec-1.c | 27 +++++++++++ > .../gcc.target/aarch64/memtag/texec-2.c | 22 +++++++++ > .../gcc.target/aarch64/memtag/texec-3.c | 37 ++++++++++++++ > .../gcc.target/aarch64/memtag/value-init.c | 14 ++++++ > .../aarch64/memtag/vararray-gimple.c | 16 +++++++ > .../gcc.target/aarch64/memtag/vararray.c | 15 ++++++ > .../gcc.target/aarch64/memtag/vla-1.c | 39 +++++++++++++++ > .../gcc.target/aarch64/memtag/vla-2.c | 48 +++++++++++++++++++ > .../gcc.target/aarch64/memtag/zero-init.c | 14 ++++++ > gcc/testsuite/lib/target-supports.exp | 43 +++++++++++++++++ > 27 files changed, 546 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/alloca-1.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/alloca-2.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- > 3.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/cfi-mte- > memtag-frame-1.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/mte-sig.h > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize- > attribute.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/texec-2.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/texec-3.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/value-init.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/vararray- > gimple.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/vararray.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/vla-1.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/vla-2.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/memtag/zero-init.c > > 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 00000000000..40ce4a8f9a1 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-1.c > @@ -0,0 +1,15 @@ > +/* { 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...?, \[...?\], 16\n} 2 } } */ > +/* { dg-final { scan-assembler-times {\tst2g\t...?, \[...?\], 32\n} 2 } } */ > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/alloca-2.c > b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-2.c > new file mode 100644 > index 00000000000..862dc818a97 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-2.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +/* Check if we handle alloca size zero cases. */ > +int a, b, c; > +void foo (void) > +{ > + int *d = __builtin_alloca (0); > + for (;; a = b) > + d[c] = *d; > +} > + > +/* We check if and only if we tag the 'd' variable. */ > +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */ > +/* { dg-final { scan-assembler-times {stg\t...?, \[sp\]\n} 1 } } */ > 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 00000000000..090e04145e5 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-3.c > @@ -0,0 +1,28 @@ > +/* { 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; > +} > + > +/* With HWASAN_ALLOCA_POISON now calling irg of its own, the number > of > + expected irg is 3, and stg/st2g is 4 (3 for tag, 1 for untag each in their > + respective loop). */ > + > +/* { dg-final { scan-assembler-times {\tirg\t} 3 } } */ > +/* { dg-final { scan-assembler-times {stg\t...?, \[...?\], 16\n} 4 } } */ > +/* { dg-final { scan-assembler-times {st2g\t...?, \[...?\], 32\n} 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 00000000000..f95b148d9f0 > --- /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-stack' 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 00000000000..9a76c5e2d71 > --- /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-stack' is incompatible with '- > fsanitize=kernel-address'.*" "" { target *-*-* } 0 } */ > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/arguments-3.c > b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-3.c > new file mode 100644 > index 00000000000..e4eaee8edf2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/arguments-3.c > @@ -0,0 +1,3 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "--param hwasan-random-frame-tag=0" } */ > +/* { dg-warning "is ignored when \'-fsanitize=memtag-stack\' is present" "" { > 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 00000000000..98035c84666 > --- /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-stack" } */ > + > +int use (int * x); > + > +void foo (int n) > +{ > + int x = 99; > + use (&x); > +} > + > +/* { dg-final { scan-assembler-not "\tirg" } } */ > +/* { dg-final { scan-assembler-not "\tstg" } } */ > +/* { dg-final { scan-assembler-not "\tst2g" } } */ > +/* { dg-final { scan-assembler-not "\tsubg" } } */ > +/* { dg-final { scan-assembler-not "\taddg" } } */ > 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 00000000000..ea1209f6a37 > --- /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-stack' 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 00000000000..353e6974963 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +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 } } */ > +/* { dg-final { scan-assembler-not "\taddg" } } */ > 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 00000000000..3621454b619 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c > @@ -0,0 +1,28 @@ > +/* { 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); > +} > + > +/* 3 stack vars need 48 bytes (16 bytes granule x 3). Each granule holds the > + local variable stack address (8 bytes), and a padding (8 bytes). The rest > + of the stack holds LR and temporary varaibles (i.e., x19, x20, and x29). > + > + Expected: 3 stg to tag, 1 st2g + 1 stg to untag. */ > + > +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */ > +/* { dg-final { scan-assembler-times {\taddg\t...?} 2 } } */ > +/* { dg-final { scan-assembler-times {\tsubg\t...?} 3 } } */ > +/* { dg-final { scan-assembler-times {\tstg\t...?, \[sp, 48\]\n} 1 } } */ > +/* { dg-final { scan-assembler-times {\tst2g\t...?, \[sp, 32\]\n} 1 } } */ > +/* { dg-final { scan-assembler-times {\tstg\t...?, \[sp, 32\]\n} 1 } } */ > +/* { dg-final { scan-assembler-times {\tstg\t...?, \[sp, 64\]\n} 2 } } */ > +/* { dg-final { scan-assembler-times {\tstp\tx19, x20, \[sp, 16\]\n} 1 } } */ > +/* { dg-final { scan-assembler-times {\tstp\tx29, x30, \[sp, -80]!\n} 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 00000000000..98bf761967b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-struct.c > @@ -0,0 +1,22 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +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/cfi-mte-memtag-frame- > 1.c b/gcc/testsuite/gcc.target/aarch64/memtag/cfi-mte-memtag-frame-1.c > new file mode 100644 > index 00000000000..07cd03c2fd0 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/cfi-mte-memtag-frame-1.c > @@ -0,0 +1,11 @@ > +/* { dg-do compile } */ > + > +int use (int *x); > + > +void foo (int n) > +{ > + int x = 99; > + use (&x); > +} > + > +/* { dg-final { scan-assembler-times ".cfi_mte_tagged_frame" 1 } } */ > 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 00000000000..ae8006fd7f4 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c > @@ -0,0 +1,23 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +#define ARRAY_LEN 12000 > + > +int create (void); > + > +void sort (int *data, int n); > + > +void sort_array (void) > +{ > + 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 {st2g\t...?, \[...?\], 32\n} 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 00000000000..8c047582111 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c > @@ -0,0 +1,22 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O0" } */ > + > +/* Local variable 'x' is saved on the stack. */ > + > +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); > +} > + > +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */ > +/* { dg-final { scan-assembler-times {\tsubg\t...?} 1 } } */ > 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 00000000000..d20cdf580b0 > --- /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-stack -march=armv8.5-a+memtag" > +} > + > +# All done. > +dg-finish > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/mte-sig.h > b/gcc/testsuite/gcc.target/aarch64/memtag/mte-sig.h > new file mode 100644 > index 00000000000..efb3c6d187c > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/mte-sig.h > @@ -0,0 +1,15 @@ > +#include <stdlib.h> > +#include <signal.h> > +#include <string.h> > + > +void handler (int nSig) > +{ > + /* We hit the exception. Return error. */ > + exit (1); > +} > + > + > +static void setHandler (void) > +{ > + signal (SIGSEGV, handler); > +} > 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 00000000000..48ca9cf434f > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c > @@ -0,0 +1,18 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +int use (int *x); > + > +__attribute__((no_sanitize("memtag-stack"))) > +void foo (int n) > +{ > + int x = 99; > + use (&x); > +} > + > +/* { dg-final { scan-assembler-not "\tirg" } } */ > +/* { dg-final { scan-assembler-not "\tgmi" } } */ > +/* { dg-final { scan-assembler-not "\tstg" } } */ > +/* { dg-final { scan-assembler-not "\tst2g" } } */ > +/* { dg-final { scan-assembler-not "\tsubg" } } */ > +/* { dg-final { scan-assembler-not "\taddg" } } */ > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c > b/gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c > new file mode 100644 > index 00000000000..b63619b04d3 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c > @@ -0,0 +1,27 @@ > +/* { dg-do run { xfail *-*-* } } */ > +/* { dg-require-effective-target memtag_exec } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "mte-sig.h" > + > +void __attribute__((noinline)) > +use (volatile unsigned char *ptr) > +{ > + ptr[0] = 0x41; > + ptr[1] = 0x42; > +} > + > +int main(void) > +{ > + volatile unsigned char array[15]; > + volatile unsigned char *ptr = &array[0]; > + > + setHandler(); > + use (ptr); > + > + /* Write to memory beyond the 16 byte granule (offsest 0x10) MTE should > + generate an exception If the offset is less than 0x10 no SIGSEGV will > + occur. */ > + ptr[0x10] = 0x55; > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/texec-2.c > b/gcc/testsuite/gcc.target/aarch64/memtag/texec-2.c > new file mode 100644 > index 00000000000..0fbbe2f0778 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/texec-2.c > @@ -0,0 +1,22 @@ > +/* { dg-do run { xfail *-*-* } } */ > +/* { dg-require-effective-target memtag_exec } */ > +/* { dg-additional-options "-O2" } */ > +#include "mte-sig.h" > + > +void __attribute__((noinline)) > +use (volatile unsigned char *ptr) > +{ > + ptr[0] = 0x41; > + ptr[1] = 0x42; > +} > + > +int main (void) > +{ > + volatile unsigned char *ptr = __builtin_alloca (15); > + > + setHandler(); > + > + use (ptr); > + ptr[0x10] = 0x55; > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/texec-3.c > b/gcc/testsuite/gcc.target/aarch64/memtag/texec-3.c > new file mode 100644 > index 00000000000..490f5878ddf > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/texec-3.c > @@ -0,0 +1,37 @@ > +/* { dg-do run { xfail *-*-* } } */ > +/* { dg-require-effective-target memtag_exec } */ > +/* { dg-require-effective-target pthread } */ > +/* { dg-additional-options "-O2 -pthread" } */ > +#include "mte-sig.h" > +#include <pthread.h> > + > +void __attribute__((noinline)) > +use (volatile unsigned char *ptr) > +{ > + ptr[0] = 0x41; > + ptr[1] = 0x42; > +} > + > +/* The thread in which we allocate and then we try to read out of the > + allocation pool. */ > +void *thread_test (void *) > +{ > + volatile unsigned char *ptr = __builtin_alloca (15); > + > + setHandler(); > + > + use (ptr); > + ptr[0x10] = 0x55; > + return 0; > +} > + > + > +int main (void) > +{ > + pthread_t thread; > + pthread_create (&thread, NULL, thread_test, NULL); > + pthread_join (thread, NULL); > + __builtin_printf ("End of line\n"); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/value-init.c > b/gcc/testsuite/gcc.target/aarch64/memtag/value-init.c > new file mode 100644 > index 00000000000..7f2c9d3123e > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/value-init.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +void use (int *); > + > +void foo (void) > +{ > + int x = 42; > + use(&x); > +} > + > +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */ > +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 16\]\n} 2 } } */ > + > 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 00000000000..302964d277b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c > @@ -0,0 +1,16 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-fdump-tree-asan -O2" } */ > + > +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 00000000000..563412fbe2b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/vararray.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +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 {stg\t...?, \[...?\], 16\n} 3 } } */ > +/* { dg-final { scan-assembler-times {st2g\t...?, \[...?\], 32\n} 3 } } */ > +/* { dg-final { scan-assembler-times {\taddg\t} 0 } } */ > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/vla-1.c > b/gcc/testsuite/gcc.target/aarch64/memtag/vla-1.c > new file mode 100644 > index 00000000000..1ad74fe67d5 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/vla-1.c > @@ -0,0 +1,39 @@ > +/* { dg-do run } */ > +/* { dg-require-effective-target memtag_exec } */ > +/* { dg-additional-options "-O2" } */ > + > +#include <string.h> > +#include "mte-sig.h" > + > +void > +bar (int i, char *b) > +{ > + __builtin_printf ("i = %d, b+i = %s \n", i, b + i); > +} > + > +void > +foo (int size) > +{ > + int i; > + for (i = 0; i < size; i++) > + { > + char temp[size]; > + memset (temp, 'B', size); > + temp[size-1] = '\0'; > + { > + char temp2[size]; > + memset (temp2, 'A', size); > + temp2[size-1] = '\0'; > + bar (i, temp2); > + } > + bar (i, temp); > + } > +} > + > +int main (void) > +{ > + setHandler (); > + foo (10); > + foo (3); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/vla-2.c > b/gcc/testsuite/gcc.target/aarch64/memtag/vla-2.c > new file mode 100644 > index 00000000000..526306a5e60 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/vla-2.c > @@ -0,0 +1,48 @@ > + > +/* { dg-do run { xfail *-*-* } } */ > +/* { dg-require-effective-target memtag_exec } */ > +/* { dg-additional-options "-O2" } */ > + > +#include "mte-sig.h" > + > +/* Testing that a function with outgoing arguments correctly decrements the > + stack pointer when a vararray goes out of scope. */ > + > +const char * __attribute__((noinline)) > +other (int argc, int a, int b, int c, int d, int e, int f, > + int g, int h, int i, int j, int k, int l) > +{ > + const char ** other; > + { > + const char * test_array[argc]; > + test_array[0] = "test string"; > + test_array[argc - 1] = "hello"; > + /* To prevent optimisation. */ > + __builtin_printf ("While the value stored in our test_array is: %s\n", > + test_array[argc - 1]); > + other = test_array; > + } > + /* With the below function call (the one with many arguments), some of the > + arguments have to be put on the stack, which means we have to reserve > some > + space on the stack for these arguments and that the VLA is stored at a > + position that is not the stack pointer. */ > + __builtin_printf ("Our numbers today are: %d, %d, %d, %d, %d, %d, %d, > %d, \ > +%d, %d, %d, %d\n", > + a, b, c, d, e, f, g, h, i, j, k, l); > + /* This should fail due to a bad read access. */ > + return other[0]; > +} > + > +int > +main (void) > +{ > + int a, b, c, d, e, f, g, h, i, j, k, l; > + > + setHandler(); > + const char * retval = other (1, a, b, c, d, e, f, g, h, i, j, k, l); > + /* Numbers don't matter here, just want to ensure the program is reading > them > + so we know they won't be optimised out. */ > + if (retval) > + return 1; > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/zero-init.c > b/gcc/testsuite/gcc.target/aarch64/memtag/zero-init.c > new file mode 100644 > index 00000000000..75980e8d430 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/memtag/zero-init.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-additional-options "-O2" } */ > + > +void use (int *); > + > +void foo (void) > +{ > + int x = 0; > + use (&x); > +} > + > +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */ > +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 16\]\n} 2 } } */ > + > diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target- > supports.exp > index 1acfb373beb..072a195d1d1 100644 > --- a/gcc/testsuite/lib/target-supports.exp > +++ b/gcc/testsuite/lib/target-supports.exp > @@ -4986,6 +4986,17 @@ proc check_effective_target_aarch64_sve1_only { > } { > && ![check_effective_target_aarch64_sve2] }] > } > > +# Return 1 if this is an AArch64 target supporting MTE. > +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 { > @@ -14674,3 +14685,35 @@ proc check_effective_target_fentry { } { > } > }] > } > + > +# Return 1 if target can compile and run binary for stack > +# sanitization, 0 otherwise. > +proc check_effective_target_memtag_exec {} { > + if ![check_runtime memtag_exec { > + #ifdef __cplusplus > + extern "C" { > + #endif > + extern int prctl(int, unsigned long, unsigned long, unsigned long, > unsigned long); > + #ifdef __cplusplus > + } > + #endif > + int main (void) { > + #define PR_SET_TAGGED_ADDR_CTRL 55 > + #define PR_GET_TAGGED_ADDR_CTRL 56 > + #define PR_TAGGED_ADDR_ENABLE (1UL << 0) > + #define PR_MTE_TCF_SYNC (1UL << 1) > + #define PR_MTE_TAG_SHIFT 3 > + if (prctl (PR_GET_TAGGED_ADDR_CTRL, 0,0,0,0) == -1) > + return -1; > + if (prctl (PR_SET_TAGGED_ADDR_CTRL, > + PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC > + | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0) == -1 > + || !prctl (PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)) > + return 1; > + return 0; > + } > + }] { > + return 0; > + } > + return 1; > +} > -- > 2.52.0
