===================================================================
@@ -43,4 +43,9 @@
} \
while (0)
+#ifdef TARGET_LIBC_PROVIDES_TLS_SSP
+/* Aarch64 glibc provides __stack_chk_guard in [tp - 0x8]. */
+#define TARGET_THREAD_SSP_OFFSET (-1 * GET_MODE_SIZE (ptr_mode))
+#endif
+
#endif /* GCC_AARCH64_LINUX_H */
===================================================================
@@ -99,6 +99,10 @@
UNSPEC_TLSDESC
UNSPEC_USHL_2S
UNSPEC_VSTRUCTDUMMY
+ UNSPEC_SP_SET
+ UNSPEC_SP_TEST
+ UNSPEC_SP_TLS_SET
+ UNSPEC_SP_TLS_TEST
])
(define_c_enum "unspecv" [
@@ -3625,6 +3629,80 @@
DONE;
})
+
+;; Named patterns for stack smashing protection.
+(define_expand "stack_protect_set"
+ [(match_operand 0 "memory_operand")
+ (match_operand 1 "memory_operand")]
+ ""
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_reg_rtx (Pmode);
+ emit_insn (gen_aarch64_load_tp_hard (tlsreg));
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+
+ emit_insn ((mode == DImode
+ ? gen_stack_protect_set_di
+ : gen_stack_protect_set_si) (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "stack_protect_set_<mode>"
+ [(set (match_operand:PTR 0 "memory_operand" "=m")
+ (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
+ UNSPEC_SP_SET))
+ (set (match_scratch:PTR 2 "=&r") (const_int 0))]
+ ""
+ "ldr\\t%x2, %1\;str\\t%x2, %0\;mov\t%x2,0"
+ [(set_attr "length" "12")])
+
+(define_expand "stack_protect_test"
+ [(match_operand 0 "memory_operand")
+ (match_operand 1 "memory_operand")
+ (match_operand 2)]
+ ""
+{
+
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_reg_rtx (Pmode);
+ emit_insn (gen_aarch64_load_tp_hard (tlsreg));
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+
+ rtx result = gen_reg_rtx (Pmode);
+
+ enum machine_mode mode = GET_MODE (operands[0]);
+
+ emit_insn ((mode == DImode
+ ? gen_stack_protect_test_di
+ : gen_stack_protect_test_si) (result,
+ operands[0],
+ operands[1]));
+
+ if (mode == DImode)
+ emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
+ result, const0_rtx, operands[2]));
+ else
+ emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
+ result, const0_rtx, operands[2]));
+ DONE;
+})
+
+(define_insn "stack_protect_test_<mode>"
+ [(set (match_operand:PTR 0 "register_operand")
+ (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
+ (match_operand:PTR 2 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (clobber (match_scratch:PTR 3 "=&r"))]
+ ""
+ "ldr\t%x3, %x1\;ldr\t%x0, %x2\;eor\t%x0, %x3, %x0"
+ [(set_attr "length" "12")])
+
;; AdvSIMD Stuff
(include "aarch64-simd.md")
===================================================================
@@ -27127,6 +27127,35 @@
fi
+# Test for tls based stack protector support in target C library.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking TLS stack guard support in target C library" >&5
+$as_echo_n "checking TLS stack guard support in target C library... " >&6; }
+if test "${gcc_cv_libc_provides_tls_ssp+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_libc_provides_tls_ssp=no
+ case "$target" in
+ aarch64-*-linux* | aarch64-*-kfreebsd*-gnu | aarch64-*-knetbsd*-gnu)
+ # glibc 2.19 and later provides TLS access to stack guard canary
+ # currently set for Aarch64.
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 19 ); then :
+ gcc_cv_libc_provides_tls_ssp=yes
+fi
+ ;;
+ *) gcc_cv_libc_provides_tls_ssp=no ;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_libc_provides_tls_ssp" >&5
+$as_echo "$gcc_cv_libc_provides_tls_ssp" >&6; }
+
+if test x$gcc_cv_libc_provides_tls_ssp = xyes; then
+
+$as_echo "#define TARGET_LIBC_PROVIDES_TLS_SSP 1" >>confdefs.h
+
+fi
+
# Test for <sys/sdt.h> on the target.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking sys/sdt.h in the target C library" >&5
===================================================================
@@ -1,6 +1,6 @@
/* Test that stack protection is done on chosen functions. */
-/* { dg-do compile { target i?86-*-* x86_64-*-* rs6000-*-* s390x-*-* } } */
+/* { dg-do compile { target i?86-*-* x86_64-*-* rs6000-*-* s390x-*-* aarch64-*-* } } */
/* { dg-options "-O2 -fstack-protector-strong" } */
#include<string.h>
===================================================================
@@ -1,6 +1,6 @@
/* Test that stack protection is done on chosen functions. */
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-do compile { target i?86-*-* x86_64-*-* aarch64*-*-* } } */
/* { dg-options "-O2 -fstack-protector-strong" } */
class A
===================================================================
@@ -1828,6 +1828,12 @@
#endif
+/* Define if your target C library provides TLS stack protector support. */
+#ifndef USED_FOR_TARGET
+#undef TARGET_LIBC_PROVIDES_TLS_SSP
+#endif
+
+
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#ifndef USED_FOR_TARGET
#undef TIME_WITH_SYS_TIME
===================================================================
@@ -4896,6 +4896,24 @@
[Define if your target C library provides stack protector support])
fi
+# Test for tls based stack protector support in target C library.
+AC_CACHE_CHECK(TLS stack guard support in target C library,
+ gcc_cv_libc_provides_tls_ssp,
+ [gcc_cv_libc_provides_tls_ssp=no
+ case "$target" in
+ aarch64-*-linux* | aarch64-*-kfreebsd*-gnu | aarch64-*-knetbsd*-gnu)
+ # glibc 2.19 and later provides TLS access to stack guard canary
+ # currently set for Aarch64.
+ GCC_GLIBC_VERSION_GTE_IFELSE([2], [19], [gcc_cv_libc_provides_tls_ssp=yes])
+ ;;
+ *) gcc_cv_libc_provides_tls_ssp=no ;;
+ esac])
+
+if test x$gcc_cv_libc_provides_tls_ssp = xyes; then
+ AC_DEFINE(TARGET_LIBC_PROVIDES_TLS_SSP, 1,
+ [Define if your target C library provides TLS stack protector support.])
+fi
+
# Test for <sys/sdt.h> on the target.
GCC_TARGET_TEMPLATE([HAVE_SYS_SDT_H])
AC_MSG_CHECKING(sys/sdt.h in the target C library)