diff mbox

[RFC,AARCH64] Machine descriptions to support stack smashing protection

Message ID CAJK_mQ29s6rDg+_omfL6Hvx-VYhERaCdv5Tjak3iFSAnkdMqiA@mail.gmail.com
State New
Headers show

Commit Message

Venkataramanan Kumar Nov. 19, 2013, 10:56 a.m. UTC
Hi Maintainers,

This is RFC patch that adds machine descriptions to support stack smashing
protection in AArch64.

I have written a very simple patch that prints "stack set" and "stack test"
as template of instructions.

I had 2 assumptions.

1) For "stack_protect_set" and "stack_protect_test", I
used "memory_operand" as predicate.

GCC pushes the memory operand in a register much
earlier during expand phase before these patterns are invoked.

So assuming that I will get a memory operand "__stack_chk_gaurd" in
a register when we are not using TLS based stack guard.

2) For the TLS case, assuming stack guard value will be stored at "-8"
offset from "tp" GCC generates below code for stack set.


        mrs     x0, tpidr_el0
        ldr     x1, [x0,-8]
        str     x1, [x29,24]
        mov     x1,0

I submitted Glibc patches some time before
https://sourceware.org/ml/libc-ports/2013-08/msg00044.html.

There are few regressions, the pthread_cancel tests in glibc fails I am
currently debugging :(.

GCC with the patch generates below code for stack test

        ldr     x1, [x29,24]
        ldr     x0, [x0,-8]
        eor     x0, x1, x0
        cbnz    x0, .L4
.................................
......................................
.L4:
        bl      __stack_chk_f


I generate "eor" since it has 2 purpose one for checking equality, and  two
 for clearing the canary loaded register.

Request your feedback to shape this into a better patch.

regards,
Venkat.
diff mbox

Patch

Index: gcc/testsuite/gcc.dg/pr46440.c
===================================================================
--- gcc/testsuite/gcc.dg/pr46440.c	(revision 204932)
+++ gcc/testsuite/gcc.dg/pr46440.c	(working copy)
@@ -1,7 +1,6 @@ 
 /* PR rtl-optimization/46440 */
 /* { dg-do compile } */
 /* { dg-options "-O -fstack-protector -fno-tree-dominator-opts -fno-tree-fre" } */
-/* { dg-require-effective-target fstack_protector } */
 
 int i;
 
Index: gcc/testsuite/gcc.dg/ssp-1.c
===================================================================
--- gcc/testsuite/gcc.dg/ssp-1.c	(revision 204932)
+++ gcc/testsuite/gcc.dg/ssp-1.c	(working copy)
@@ -1,6 +1,4 @@ 
-/* { dg-do run { target native } } */
 /* { dg-options "-fstack-protector" } */
-/* { dg-require-effective-target fstack_protector } */
 
 #include <stdlib.h>
 
Index: gcc/testsuite/gcc.dg/pr47766.c
===================================================================
--- gcc/testsuite/gcc.dg/pr47766.c	(revision 204932)
+++ gcc/testsuite/gcc.dg/pr47766.c	(working copy)
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-O2 -fstack-protector" } */
-/* { dg-require-effective-target fstack_protector } */
 
 int
 parse_opt (int key)
Index: gcc/testsuite/gcc.dg/ssp-2.c
===================================================================
--- gcc/testsuite/gcc.dg/ssp-2.c	(revision 204932)
+++ gcc/testsuite/gcc.dg/ssp-2.c	(working copy)
@@ -1,7 +1,5 @@ 
-/* { dg-do run { target native } } */
 /* { dg-options "-fstack-protector" } */
 /* { dg-options "-fstack-protector -Wl,-multiply_defined,suppress" { target *-*-darwin* } } */
-/* { dg-require-effective-target fstack_protector } */
 
 #include <stdlib.h>
 
Index: gcc/testsuite/gcc.dg/fstack-protector-strong.c
===================================================================
--- gcc/testsuite/gcc.dg/fstack-protector-strong.c	(revision 204932)
+++ gcc/testsuite/gcc.dg/fstack-protector-strong.c	(working copy)
@@ -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>
Index: gcc/testsuite/g++.dg/fstack-protector-strong.C
===================================================================
--- gcc/testsuite/g++.dg/fstack-protector-strong.C	(revision 204932)
+++ gcc/testsuite/g++.dg/fstack-protector-strong.C	(working copy)
@@ -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
Index: gcc/config/aarch64/aarch64-linux.h
===================================================================
--- gcc/config/aarch64/aarch64-linux.h	(revision 204932)
+++ gcc/config/aarch64/aarch64-linux.h	(working copy)
@@ -43,4 +43,9 @@ 
     }						\
   while (0)
 
+#ifdef TARGET_LIBC_PROVIDES_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 */
Index: gcc/config/aarch64/aarch64.md
===================================================================
--- gcc/config/aarch64/aarch64.md	(revision 204932)
+++ gcc/config/aarch64/aarch64.md	(working copy)
@@ -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" [
@@ -320,6 +324,7 @@ 
 (include "../arm/cortex-a53.md")
 (include "../arm/cortex-a15.md")
 
+
 ;; -------------------------------------------------------------------
 ;; Jumps and other miscellaneous insns
 ;; -------------------------------------------------------------------
@@ -4181,6 +4186,82 @@ 
   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")