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


Reply via email to