aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2017-01-17 23:02:42 +0100
committerSegher Boessenkool <segher@gcc.gnu.org>2017-01-17 23:02:42 +0100
commit1b3254e4bbe82245421a55324bc8fe34a99c6e3c (patch)
treed62c5d81ea1e4aeabc83bba0c79cda21639f4836 /gcc
parent4ed04e93c2c9a8266be6a1cb6b11858add8aad70 (diff)
downloadgcc-1b3254e4bbe82245421a55324bc8fe34a99c6e3c.zip
gcc-1b3254e4bbe82245421a55324bc8fe34a99c6e3c.tar.gz
gcc-1b3254e4bbe82245421a55324bc8fe34a99c6e3c.tar.bz2
-mstack-protector-guard and friends (PR78875)
Currently, on PowerPC, code compiled with -fstack-protector will load the canary from -0x7010(13) (for -m64) or from -0x7008(2) (for -m32) if GCC was compiled against GNU libc 2.4 or newer or some other libc that supports -fstack-protector, and from the global variable __stack_chk_guard otherwise. This does not work well for Linux and other OS kernels and similar. For such non-standard applications, this patch creates a few new command-line options. The relevant new use cases are: -mstack-protector-guard=global Use the __stack_chk_guard variable, no matter how this GCC was configured. -mstack-protector-guard=tls Use the canary from TLS. This will error out if this GCC was built with a C library that does not support it. -mstack-protector-guard=tls -mstack-protector-register=<reg> -mstack-protector-offset=<offset> Load the canary from offset <off> from base register <reg>. PR target/78875 * config/rs6000/rs6000-opts.h (stack_protector_guard): New enum. * config/rs6000/rs6000.c (rs6000_option_override_internal): Handle the new options. * config/rs6000/rs6000.md (stack_protect_set): Handle the new more flexible settings. (stack_protect_test): Ditto. * config/rs6000/rs6000.opt (mstack-protector-guard=, mstack-protector-guard-reg=, mstack-protector-guard-offset=): New options. * doc/invoke.texi (Option Summary) [RS/6000 and PowerPC Options]: Add -mstack-protector-guard=, -mstack-protector-guard-reg=, and -mstack-protector-guard-offset=. (RS/6000 and PowerPC Options): Ditto. gcc/testsuite/ * gcc.target/powerpc/ssp-1.c: New testcase. * gcc.target/powerpc/ssp-2.c: New testcase. From-SVN: r244556
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/rs6000/rs6000-opts.h6
-rw-r--r--gcc/config/rs6000/rs6000.c48
-rw-r--r--gcc/config/rs6000/rs6000.md49
-rw-r--r--gcc/config/rs6000/rs6000.opt28
-rw-r--r--gcc/doc/invoke.texi19
-rw-r--r--gcc/testsuite/ChangeLog6
7 files changed, 153 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 15a0718..e2ea014 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2017-01-17 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/78875
+ * config/rs6000/rs6000-opts.h (stack_protector_guard): New enum.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Handle
+ the new options.
+ * config/rs6000/rs6000.md (stack_protect_set): Handle the new more
+ flexible settings.
+ (stack_protect_test): Ditto.
+ * config/rs6000/rs6000.opt (mstack-protector-guard=,
+ mstack-protector-guard-reg=, mstack-protector-guard-offset=): New
+ options.
+ * doc/invoke.texi (Option Summary) [RS/6000 and PowerPC Options]:
+ Add -mstack-protector-guard=, -mstack-protector-guard-reg=, and
+ -mstack-protector-guard-offset=.
+ (RS/6000 and PowerPC Options): Ditto.
+
2017-01-17 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.h (MASK_CLASS_P): New define.
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
index d58b980..086217a 100644
--- a/gcc/config/rs6000/rs6000-opts.h
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -154,6 +154,12 @@ enum rs6000_vector {
VECTOR_OTHER /* Some other vector unit */
};
+/* Where to get the canary for the stack protector. */
+enum stack_protector_guard {
+ SSP_TLS, /* per-thread canary in TLS block */
+ SSP_GLOBAL /* global canary */
+};
+
/* No enumeration is defined to index the -mcpu= values (entries in
processor_target_table), with the type int being used instead, but
we need to distinguish the special "native" value. */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 63c62c3..72ef8e1e 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4942,6 +4942,54 @@ rs6000_option_override_internal (bool global_init_p)
atoi (rs6000_sched_insert_nops_str));
}
+ /* Handle stack protector */
+ if (!global_options_set.x_rs6000_stack_protector_guard)
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rs6000_stack_protector_guard = SSP_TLS;
+#else
+ rs6000_stack_protector_guard = SSP_GLOBAL;
+#endif
+
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rs6000_stack_protector_guard_offset = TARGET_THREAD_SSP_OFFSET;
+ rs6000_stack_protector_guard_reg = TARGET_64BIT ? 13 : 2;
+#endif
+
+ if (global_options_set.x_rs6000_stack_protector_guard_offset_str)
+ {
+ char *endp;
+ const char *str = rs6000_stack_protector_guard_offset_str;
+
+ errno = 0;
+ long offset = strtol (str, &endp, 0);
+ if (!*str || *endp || errno)
+ error ("%qs is not a valid number "
+ "in -mstack-protector-guard-offset=", str);
+
+ if (!IN_RANGE (offset, -0x8000, 0x7fff)
+ || (TARGET_64BIT && (offset & 3)))
+ error ("%qs is not a valid offset "
+ "in -mstack-protector-guard-offset=", str);
+
+ rs6000_stack_protector_guard_offset = offset;
+ }
+
+ if (global_options_set.x_rs6000_stack_protector_guard_reg_str)
+ {
+ const char *str = rs6000_stack_protector_guard_reg_str;
+ int reg = decode_reg_name (str);
+
+ if (!IN_RANGE (reg, 1, 31))
+ error ("%qs is not a valid base register "
+ "in -mstack-protector-guard-reg=", str);
+
+ rs6000_stack_protector_guard_reg = reg;
+ }
+
+ if (rs6000_stack_protector_guard == SSP_TLS
+ && !IN_RANGE (rs6000_stack_protector_guard_reg, 1, 31))
+ error ("-mstack-protector-guard=tls needs a valid base register");
+
if (global_init_p)
{
#ifdef TARGET_REGNAMES
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f00334a..ff602fa 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -11681,19 +11681,23 @@
(define_expand "stack_protect_set"
- [(match_operand 0 "memory_operand" "")
- (match_operand 1 "memory_operand" "")]
+ [(match_operand 0 "memory_operand")
+ (match_operand 1 "memory_operand")]
""
{
-#ifdef TARGET_THREAD_SSP_OFFSET
- rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
- rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
- operands[1] = gen_rtx_MEM (Pmode, addr);
-#endif
+ if (rs6000_stack_protector_guard == SSP_TLS)
+ {
+ rtx reg = gen_rtx_REG (Pmode, rs6000_stack_protector_guard_reg);
+ rtx offset = GEN_INT (rs6000_stack_protector_guard_offset);
+ rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+ }
+
if (TARGET_64BIT)
emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
else
emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+
DONE;
})
@@ -11716,21 +11720,26 @@
(set_attr "length" "12")])
(define_expand "stack_protect_test"
- [(match_operand 0 "memory_operand" "")
- (match_operand 1 "memory_operand" "")
- (match_operand 2 "" "")]
+ [(match_operand 0 "memory_operand")
+ (match_operand 1 "memory_operand")
+ (match_operand 2 "")]
""
{
- rtx test, op0, op1;
-#ifdef TARGET_THREAD_SSP_OFFSET
- rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
- rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
- operands[1] = gen_rtx_MEM (Pmode, addr);
-#endif
- op0 = operands[0];
- op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]), UNSPEC_SP_TEST);
- test = gen_rtx_EQ (VOIDmode, op0, op1);
- emit_jump_insn (gen_cbranchsi4 (test, op0, op1, operands[2]));
+ rtx guard = operands[1];
+
+ if (rs6000_stack_protector_guard == SSP_TLS)
+ {
+ rtx reg = gen_rtx_REG (Pmode, rs6000_stack_protector_guard_reg);
+ rtx offset = GEN_INT (rs6000_stack_protector_guard_offset);
+ rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
+ guard = gen_rtx_MEM (Pmode, addr);
+ }
+
+ operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, guard), UNSPEC_SP_TEST);
+ rtx test = gen_rtx_EQ (VOIDmode, operands[0], operands[1]);
+ rtx jump = gen_cbranchsi4 (test, operands[0], operands[1], operands[2]);
+ emit_jump_insn (jump);
+
DONE;
})
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index c806bf7..803753e 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -672,3 +672,31 @@ Enable default conversions between __float128 & long double.
mvsx-small-integer
Target Report Mask(VSX_SMALL_INTEGER) Var(rs6000_isa_flags)
Enable small integers to be in VSX registers.
+
+mstack-protector-guard=
+Target RejectNegative Joined Enum(stack_protector_guard) Var(rs6000_stack_protector_guard) Init(SSP_TLS)
+Use given stack-protector guard.
+
+Enum
+Name(stack_protector_guard) Type(enum stack_protector_guard)
+Valid arguments to -mstack-protector-guard=:
+
+EnumValue
+Enum(stack_protector_guard) String(tls) Value(SSP_TLS)
+
+EnumValue
+Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
+
+mstack-protector-guard-reg=
+Target RejectNegative Joined Var(rs6000_stack_protector_guard_reg_str)
+Use the given base register for addressing the stack-protector guard.
+
+TargetVariable
+int rs6000_stack_protector_guard_reg = 0
+
+mstack-protector-guard-offset=
+Target RejectNegative Joined Integer Var(rs6000_stack_protector_guard_offset_str)
+Use the given offset for addressing the stack-protector guard.
+
+TargetVariable
+long rs6000_stack_protector_guard_offset = 0
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e0624da..cac3d8b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1041,6 +1041,8 @@ See RS/6000 and PowerPC Options.
-mupper-regs -mno-upper-regs @gol
-mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol
-mgnu-attribute -mno-gnu-attribute @gol
+-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol
+-mstack-protector-guard-offset=@var{offset} @gol
-mlra -mno-lra}
@emph{RX Options}
@@ -22202,6 +22204,23 @@ that is compatible with functions compiled with older versions of
GCC.
The @option{-mno-compat-align-parm} option is the default.
+
+@item -mstack-protector-guard=@var{guard}
+@itemx -mstack-protector-guard-reg=@var{reg}
+@itemx -mstack-protector-guard-offset=@var{offset}
+@opindex mstack-protector-guard
+@opindex mstack-protector-guard-reg
+@opindex mstack-protector-guard-offset
+Generate stack protection code using canary at @var{guard}. Supported
+locations are @samp{global} for global canary or @samp{tls} for per-thread
+canary in the TLS block (the default with GNU libc version 2.4 or later).
+
+With the latter choice the options
+@option{-mstack-protector-guard-reg=@var{reg}} and
+@option{-mstack-protector-guard-offset=@var{offset}} furthermore specify
+which register to use as base register for reading the canary, and from what
+offset from that base register. The default for those is as specified in the
+relevant ABI.
@end table
@node RX Options
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index eb1e3cc..ea74ebd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-01-17 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/78875
+ * gcc.target/powerpc/ssp-1.c: New testcase.
+ * gcc.target/powerpc/ssp-2.c: New testcase.
+
2017-01-17 Wilco Dijkstra <wdijkstr@arm.com>
* gcc.target/aarch64/eh_return.c: New test.