This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Enable -fstack-protector on MIPS


MIPS is !FRAME_GROWS_DOWNWARD so -fprotector-stack is not supported currently.
This patch enables FRAME_GROWS_DOWNWARD with -fstack-protector*.

I had some plans trying to make FRAME_GROWS_DOWNWARD the default in order to
avoid yet another mode of operation but as it turns out having the SW frame
pointer be identical to the stack pointer helps large stack displacement
constants to be better optimized by the pre-RA RTL optimizers.  Therefore, in
the patch below, FRAME_GROWS_DOWNWARD is only enabled for -fstack-protector
specifically.  We could of course still improve post-RA optimizers so that
-fstack-protector code is more optimal but that could be done later.

In order to ensure that FRAME_GROWS_DOWNWARD actually works beyond the
stack-protector tests I enabled FRAME_GROWS_DOWNWARD while testing this patch,
like this:

--- /tmp/mips.h	2009-04-26 20:51:14.000000000 -0700
+++ mips.h	2009-04-26 20:51:15.000000000 -0700
@@ -2079,7 +2079,7 @@ enum reg_class
 
 /* Stack layout; function entry, exit and calling.  */
 
-#define FRAME_GROWS_DOWNWARD flag_stack_protect
+#define FRAME_GROWS_DOWNWARD (1||flag_stack_protect)
 
 #define STACK_GROWS_DOWNWARD

With the patch and this together, I regression-tested:

  * mipsisa64r2-elf with the default EABI
  * mipsisa64r2-elfoabi with {,-mips16,-mips32r2}

I also boostrapped/regtested on mips64octeon-linux.

The gcc.dg/ssp-*.c are passing with one exception.  ssp-1 fails to link with:

  CALL16 reloc at 0xac not against global symbol

I need to look at this a little more but it's definitely unrelated.  We get
confused by __stack_chk_fail being static.  If I remove static ssp-1 works
too.

OK to install?

Adam


	* config/mips/mips.h (FRAME_GROWS_DOWNWARD,
	MIPS_GP_SAVE_AREA_SIZE): Define new macros.
	(STARTING_FRAME_OFFSET): Return 0 if FRAME_GROWS_DOWNWARD.  Use
	MIPS_GP_SAVE_AREA_SIZE.
	* config/mips/mips.c (struct mips_frame_info): Update comment
	before arg_pointer_offset and hard_frame_pointer_offset.
	(mips_compute_frame_info): Update diagram before function: to
	correctly use stack_pointer_rtx for fp_sp_offset and gp_sp_offset, to
	indicate the position of frame_pointer_rtx with -fstack-protector and
	to show args_size.  Use MIPS_GP_SAVE_AREA_SIZE to set
	cprestore_size.
	(mips_initial_elimination_offset): Update for FRAME_GROWS_DOWNWARD.

Index: gcc/config/mips/mips.h
===================================================================
--- gcc.orig/config/mips/mips.h	2009-04-26 20:38:19.000000000 -0700
+++ gcc/config/mips/mips.h	2009-04-27 11:18:50.000000000 -0700
@@ -2081,12 +2081,20 @@ enum reg_class
 
 #define STACK_GROWS_DOWNWARD
 
-/* The offset of the first local variable from the beginning of the frame.
-   See mips_compute_frame_info for details about the frame layout.  */
+#define FRAME_GROWS_DOWNWARD flag_stack_protect
 
-#define STARTING_FRAME_OFFSET						\
-  (crtl->outgoing_args_size					\
-   + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
+/* Size of the area allocated in the frame to save the GP.  */
+
+#define MIPS_GP_SAVE_AREA_SIZE \
+  (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)
+
+/* The offset of the first local variable from the frame pointer.  See
+   mips_compute_frame_info for details about the frame layout.  */
+
+#define STARTING_FRAME_OFFSET				\
+  (FRAME_GROWS_DOWNWARD					\
+   ? 0							\
+   : crtl->outgoing_args_size + MIPS_GP_SAVE_AREA_SIZE)
 
 #define RETURN_ADDR_RTX mips_return_addr
 
Index: gcc/config/mips/mips.c
===================================================================
--- gcc.orig/config/mips/mips.c	2009-04-26 20:40:50.000000000 -0700
+++ gcc/config/mips/mips.c	2009-04-26 20:41:02.000000000 -0700
@@ -285,10 +285,10 @@ struct mips_frame_info GTY(()) {
   HOST_WIDE_INT acc_sp_offset;
   HOST_WIDE_INT cop0_sp_offset;
 
-  /* The offset of arg_pointer_rtx from frame_pointer_rtx.  */
+  /* The offset of arg_pointer_rtx from the bottom of the frame.  */
   HOST_WIDE_INT arg_pointer_offset;
 
-  /* The offset of hard_frame_pointer_rtx from frame_pointer_rtx.  */
+  /* The offset of hard_frame_pointer_rtx from the bottom of the frame.  */
   HOST_WIDE_INT hard_frame_pointer_offset;
 };
 
@@ -8670,16 +8670,16 @@ mips_save_reg_p (unsigned int regno)
 	|                               |       + UNITS_PER_WORD
 	|  accumulator save area        |
 	|                               |
-	+-------------------------------+ <-- frame_pointer_rtx + fp_sp_offset
+	+-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
 	|                               |       + UNITS_PER_HWFPVALUE
 	|  FPR save area                |
 	|                               |
-	+-------------------------------+ <-- frame_pointer_rtx + gp_sp_offset
+	+-------------------------------+ <-- stack_pointer_rtx + gp_sp_offset
 	|                               |       + UNITS_PER_WORD
 	|  GPR save area                |
 	|                               |
-	+-------------------------------+
-	|                               | \
+	+-------------------------------+ <-- frame_pointer_rtx with
+	|                               | \     -fstack-protector
 	|  local variables              |  | var_size
 	|                               | /
 	+-------------------------------+
@@ -8687,16 +8687,17 @@ mips_save_reg_p (unsigned int regno)
 	|  $gp save area                |  | cprestore_size
 	|                               | /
       P +-------------------------------+ <-- hard_frame_pointer_rtx for
-	|                               |       MIPS16 code
-	|  outgoing stack arguments     |
-	|                               |
-	+-------------------------------+
-	|                               |
-	|  caller-allocated save area   |
-	|  for register arguments       |
-	|                               |
+	|                               | \     MIPS16 code
+	|  outgoing stack arguments     |  |
+	|                               |  |
+	+-------------------------------+  | args_size
+	|                               |  |
+	|  caller-allocated save area   |  |
+	|  for register arguments       |  |
+	|                               | /
 	+-------------------------------+ <-- stack_pointer_rtx
-					      frame_pointer_rtx
+					      frame_pointer_rtx without
+					        -fstack-protector
 					      hard_frame_pointer_rtx for
 						non-MIPS16 code.
 
@@ -8741,10 +8742,10 @@ mips_compute_frame_info (void)
 
   cfun->machine->global_pointer = mips_global_pointer ();
 
-  /* The first STARTING_FRAME_OFFSET bytes contain the outgoing argument
-     area and the $gp save slot.  This area isn't needed in leaf functions,
-     but if the target-independent frame size is nonzero, we're committed
-     to allocating it anyway.  */
+  /* The first two blocks contain the outgoing argument area and the $gp save
+     slot.  This area isn't needed in leaf functions, but if the
+     target-independent frame size is nonzero, we're committed to allocating
+     it anyway.  */
   if (size == 0 && current_function_is_leaf)
     {
       /* The MIPS 3.0 linker does not like functions that dynamically
@@ -8760,7 +8761,7 @@ mips_compute_frame_info (void)
   else
     {
       frame->args_size = crtl->outgoing_args_size;
-      frame->cprestore_size = STARTING_FRAME_OFFSET - frame->args_size;
+      frame->cprestore_size = MIPS_GP_SAVE_AREA_SIZE;
     }
   offset = frame->args_size + frame->cprestore_size;
 
@@ -8939,12 +8940,16 @@ mips_initial_elimination_offset (int fro
 
   mips_compute_frame_info ();
 
-  /* Set OFFSET to the offset from the soft frame pointer, which is also
-     the offset from the end-of-prologue stack pointer.  */
+  /* Set OFFSET to the offset from the end-of-prologue stack pointer.  */
   switch (from)
     {
     case FRAME_POINTER_REGNUM:
-      offset = 0;
+      if (FRAME_GROWS_DOWNWARD)
+	offset = (cfun->machine->frame.args_size
+		  + cfun->machine->frame.cprestore_size
+		  + cfun->machine->frame.var_size);
+      else
+	offset = 0;
       break;
 
     case ARG_POINTER_REGNUM:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]