From: Indu Bhagat <indu.bha...@oracle.com> 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: * 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-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/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 <indu.bha...@oracle.com> Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-iancule...@oracle.com> --- .../gcc.target/aarch64/memtag/alloca-1.c | 14 ++++ .../gcc.target/aarch64/memtag/alloca-3.c | 27 ++++++++ .../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 | 15 +++++ .../gcc.target/aarch64/memtag/basic-3.c | 21 ++++++ .../gcc.target/aarch64/memtag/basic-struct.c | 22 +++++++ .../aarch64/memtag/cfi-mte-memtag-frame-1.c | 11 ++++ .../gcc.target/aarch64/memtag/large-array.c | 24 +++++++ .../aarch64/memtag/local-no-escape.c | 20 ++++++ .../gcc.target/aarch64/memtag/memtag.exp | 64 +++++++++++++++++++ .../gcc.target/aarch64/memtag/mte-sig.h | 15 +++++ .../aarch64/memtag/no-sanitize-attribute.c | 17 +++++ .../gcc.target/aarch64/memtag/texec-1.c | 27 ++++++++ .../gcc.target/aarch64/memtag/texec-2.c | 22 +++++++ .../gcc.target/aarch64/memtag/value-init.c | 14 ++++ .../aarch64/memtag/vararray-gimple.c | 17 +++++ .../gcc.target/aarch64/memtag/vararray.c | 14 ++++ .../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 | 12 ++++ 25 files changed, 485 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-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/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..649ade7f9c9 --- /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 {stg\t...?, \[...?\], 16\n} 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 00000000000..c3be277b2e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/memtag/alloca-3.c @@ -0,0 +1,27 @@ +/* { 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 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 } } */ 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..c952997db89 --- /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 "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 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..70b790c6c3e --- /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 00000000000..2838c934a62 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c @@ -0,0 +1,21 @@ +/* { 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. Expected: 3 stg to tag, 1 st2g + 1 stg to + untag. */ + +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */ +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 48\]\n} 1 } } */ +/* { dg-final { scan-assembler-times {st2g\t...?, \[sp, 32\]\n} 1 } } */ +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 32\]\n} 1 } } */ +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 64\]\n} 2 } } */ 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..32c1ad7832e --- /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 {st2g\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..f233ce04d35 --- /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 (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..173fe1135bf --- /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 00000000000..ba32f43d846 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp @@ -0,0 +1,64 @@ +# 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 + +# 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; +} +# 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..0d40063dc08 --- /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-stack"))) +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/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/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..c960048d670 --- /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 00000000000..a01a5cd8a8b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/memtag/vararray.c @@ -0,0 +1,14 @@ +/* { 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 {\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 956bc0bc7ca..bae37828a0a 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -4944,6 +4944,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 { -- 2.50.0