Commit cd0b2d36 by Ramana Radhakrishnan Committed by Ramana Radhakrishnan

[AArch64] Add support for system register based stack protector canary access

2019-01-18  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>

        * config/aarch64/aarch64-opts.h (enum stack_protector_guard): New
        * config/aarch64/aarch64.c (aarch64_override_options_internal): Handle
        and put in error checks for stack protector guard options.
        (aarch64_stack_protect_guard): New.
        (TARGET_STACK_PROTECT_GUARD): Define.
        * config/aarch64/aarch64.md (UNSPEC_SSP_SYSREG): New.
        (reg_stack_protect_address<mode>): New.
        (stack_protect_set): Adjust for SSP_GLOBAL.
        (stack_protect_test): Likewise.
        * config/aarch64/aarch64.opt (-mstack-protector-guard-reg): New.
        (-mstack-protector-guard): Likewise.
        (-mstack-protector-guard-offset): Likewise.

From-SVN: r268068
parent d0bf921f
2019-01-18 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* config/aarch64/aarch64-opts.h (enum stack_protector_guard): New
* config/aarch64/aarch64.c (aarch64_override_options_internal): Handle
and put in error checks for stack protector guard options.
(aarch64_stack_protect_guard): New.
(TARGET_STACK_PROTECT_GUARD): Define.
* config/aarch64/aarch64.md (UNSPEC_SSP_SYSREG): New.
(reg_stack_protect_address<mode>): New.
(stack_protect_set): Adjust for SSP_GLOBAL.
(stack_protect_test): Likewise.
* config/aarch64/aarch64.opt (-mstack-protector-guard-reg): New.
(-mstack-protector-guard): Likewise.
(-mstack-protector-guard-offset): Likewise.
2019-01-18 Jakub Jelinek <jakub@redhat.com> 2019-01-18 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/86214 PR tree-optimization/86214
......
...@@ -92,4 +92,10 @@ enum aarch64_sve_vector_bits_enum { ...@@ -92,4 +92,10 @@ enum aarch64_sve_vector_bits_enum {
SVE_2048 = 2048 SVE_2048 = 2048
}; };
/* Where to get the canary for the stack protector. */
enum stack_protector_guard {
SSP_SYSREG, /* per-thread canary in special system register */
SSP_GLOBAL /* global canary */
};
#endif #endif
...@@ -11409,6 +11409,41 @@ aarch64_override_options_internal (struct gcc_options *opts) ...@@ -11409,6 +11409,41 @@ aarch64_override_options_internal (struct gcc_options *opts)
if (opts->x_flag_strict_volatile_bitfields < 0 && abi_version_at_least (2)) if (opts->x_flag_strict_volatile_bitfields < 0 && abi_version_at_least (2))
opts->x_flag_strict_volatile_bitfields = 1; opts->x_flag_strict_volatile_bitfields = 1;
if (aarch64_stack_protector_guard == SSP_GLOBAL
&& opts->x_aarch64_stack_protector_guard_offset_str)
{
error ("incompatible options -mstack-protector-guard=global and"
"-mstack-protector-guard-offset=%qs",
aarch64_stack_protector_guard_offset_str);
}
if (aarch64_stack_protector_guard == SSP_SYSREG
&& !(opts->x_aarch64_stack_protector_guard_offset_str
&& opts->x_aarch64_stack_protector_guard_reg_str))
{
error ("both -mstack-protector-guard-offset and "
"-mstack-protector-guard-reg must be used "
"with -mstack-protector-guard=sysreg");
}
if (opts->x_aarch64_stack_protector_guard_reg_str)
{
if (strlen (opts->x_aarch64_stack_protector_guard_reg_str) > 100)
error ("specify a system register with a small string length.");
}
if (opts->x_aarch64_stack_protector_guard_offset_str)
{
char *end;
const char *str = aarch64_stack_protector_guard_offset_str;
errno = 0;
long offs = strtol (aarch64_stack_protector_guard_offset_str, &end, 0);
if (!*str || *end || errno)
error ("%qs is not a valid offset in %qs", str,
"-mstack-protector-guard-offset=");
aarch64_stack_protector_guard_offset = offs;
}
initialize_aarch64_code_model (opts); initialize_aarch64_code_model (opts);
initialize_aarch64_tls_size (opts); initialize_aarch64_tls_size (opts);
...@@ -18671,8 +18706,24 @@ aarch64_run_selftests (void) ...@@ -18671,8 +18706,24 @@ aarch64_run_selftests (void)
} // namespace selftest } // namespace selftest
/* Implement TARGET_STACK_PROTECT_GUARD. In case of a
global variable based guard use the default else
return a null tree. */
static tree
aarch64_stack_protect_guard (void)
{
if (aarch64_stack_protector_guard == SSP_GLOBAL)
return default_stack_protect_guard ();
return NULL_TREE;
}
#endif /* #if CHECKING_P */ #endif /* #if CHECKING_P */
#undef TARGET_STACK_PROTECT_GUARD
#define TARGET_STACK_PROTECT_GUARD aarch64_stack_protect_guard
#undef TARGET_ADDRESS_COST #undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_address_cost #define TARGET_ADDRESS_COST aarch64_address_cost
......
...@@ -201,6 +201,7 @@ ...@@ -201,6 +201,7 @@
UNSPEC_UCVTF UNSPEC_UCVTF
UNSPEC_USHL_2S UNSPEC_USHL_2S
UNSPEC_VSTRUCTDUMMY UNSPEC_VSTRUCTDUMMY
UNSPEC_SSP_SYSREG
UNSPEC_SP_SET UNSPEC_SP_SET
UNSPEC_SP_TEST UNSPEC_SP_TEST
UNSPEC_RSQRT UNSPEC_RSQRT
...@@ -6774,13 +6775,46 @@ ...@@ -6774,13 +6775,46 @@
"" ""
{ {
machine_mode mode = GET_MODE (operands[0]); machine_mode mode = GET_MODE (operands[0]);
if (aarch64_stack_protector_guard != SSP_GLOBAL)
{
/* Generate access through the system register. */
rtx tmp_reg = gen_reg_rtx (mode);
if (mode == DImode)
{
emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
GEN_INT (aarch64_stack_protector_guard_offset)));
}
else
{
emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
GEN_INT (aarch64_stack_protector_guard_offset)));
}
operands[1] = gen_rtx_MEM (mode, tmp_reg);
}
emit_insn ((mode == DImode emit_insn ((mode == DImode
? gen_stack_protect_set_di ? gen_stack_protect_set_di
: gen_stack_protect_set_si) (operands[0], operands[1])); : gen_stack_protect_set_si) (operands[0], operands[1]));
DONE; DONE;
}) })
(define_insn "reg_stack_protect_address_<mode>"
[(set (match_operand:PTR 0 "register_operand" "=r")
(unspec:PTR [(const_int 0)]
UNSPEC_SSP_SYSREG))]
"aarch64_stack_protector_guard != SSP_GLOBAL"
{
char buf[150];
snprintf (buf, 150, "mrs\\t%%<w>0, %s",
aarch64_stack_protector_guard_reg_str);
output_asm_insn (buf, operands);
return "";
}
[(set_attr "type" "mrs")])
(define_insn "stack_protect_set_<mode>" (define_insn "stack_protect_set_<mode>"
[(set (match_operand:PTR 0 "memory_operand" "=m") [(set (match_operand:PTR 0 "memory_operand" "=m")
(unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")] (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
...@@ -6801,12 +6835,34 @@ ...@@ -6801,12 +6835,34 @@
machine_mode mode = GET_MODE (operands[0]); machine_mode mode = GET_MODE (operands[0]);
result = gen_reg_rtx(mode); result = gen_reg_rtx(mode);
if (aarch64_stack_protector_guard != SSP_GLOBAL)
{
/* Generate access through the system register. The
sequence we want here is the access
of the stack offset to come with
mrs scratch_reg, <system_register>
add scratch_reg, scratch_reg, :lo12:offset. */
rtx tmp_reg = gen_reg_rtx (mode);
if (mode == DImode)
{
emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
GEN_INT (aarch64_stack_protector_guard_offset)));
}
else
{
emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
GEN_INT (aarch64_stack_protector_guard_offset)));
}
operands[1] = gen_rtx_MEM (mode, tmp_reg);
}
emit_insn ((mode == DImode emit_insn ((mode == DImode
? gen_stack_protect_test_di ? gen_stack_protect_test_di
: gen_stack_protect_test_si) (result, : gen_stack_protect_test_si) (result,
operands[0], operands[0],
operands[1])); operands[1]));
if (mode == DImode) if (mode == DImode)
emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx), emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
......
...@@ -225,3 +225,33 @@ Enables verbose cost model dumping in the debug dump files. ...@@ -225,3 +225,33 @@ Enables verbose cost model dumping in the debug dump files.
mtrack-speculation mtrack-speculation
Target Var(aarch64_track_speculation) Target Var(aarch64_track_speculation)
Generate code to track when the CPU might be speculating incorrectly. Generate code to track when the CPU might be speculating incorrectly.
mstack-protector-guard=
Target RejectNegative Joined Enum(stack_protector_guard) Var(aarch64_stack_protector_guard) Init(SSP_GLOBAL)
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(sysreg) Value(SSP_SYSREG)
EnumValue
Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
mstack-protector-guard-reg=
Target Joined RejectNegative String Var(aarch64_stack_protector_guard_reg_str)
Use the system register specified on the command line as the stack protector
guard register. This option is for use with fstack-protector-strong and
not for use in user-land code.
mstack-protector-guard-offset=
Target Joined RejectNegative String Var(aarch64_stack_protector_guard_offset_str)
Use an immediate to offset from the stack protector guard register, sp_el0.
This option is for use with fstack-protector-strong and not for use in
user-land code.
TargetVariable
long aarch64_stack_protector_guard_offset = 0
...@@ -633,7 +633,9 @@ Objective-C and Objective-C++ Dialects}. ...@@ -633,7 +633,9 @@ Objective-C and Objective-C++ Dialects}.
-msign-return-address=@var{scope} @gol -msign-return-address=@var{scope} @gol
-mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}] @gol -mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}] @gol
-march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol -march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol
-moverride=@var{string} -mverbose-cost-dump -mtrack-speculation} -moverride=@var{string} -mverbose-cost-dump @gol
-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol
-mstack-protector-guard-offset=@var{offset} -mtrack-speculation }
@emph{Adapteva Epiphany Options} @emph{Adapteva Epiphany Options}
@gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol @gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol
...@@ -15606,6 +15608,42 @@ object boundary as described in the architecture specification. ...@@ -15606,6 +15608,42 @@ object boundary as described in the architecture specification.
Omit or keep the frame pointer in leaf functions. The former behavior is the Omit or keep the frame pointer in leaf functions. The former behavior is the
default. 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 a global canary or @samp{sysreg} for a
canary in an appropriate system register.
With the latter choice the options
@option{-mstack-protector-guard-reg=@var{reg}} and
@option{-mstack-protector-guard-offset=@var{offset}} furthermore specify
which system register to use as base register for reading the canary,
and from what offset from that base register. There is no default
register or offset as this is entirely for use within the Linux
kernel.
@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 a global canary or @samp{sysreg} for a
canary in an appropriate system register.
With the latter choice the options
@option{-mstack-protector-guard-reg=@var{reg}} and
@option{-mstack-protector-guard-offset=@var{offset}} furthermore specify
which system register to use as base register for reading the canary,
and from what offset from that base register. There is no default
register or offset as this is entirely for use within the Linux
kernel.
@item -mtls-dialect=desc @item -mtls-dialect=desc
@opindex mtls-dialect=desc @opindex mtls-dialect=desc
Use TLS descriptors as the thread-local storage mechanism for dynamic accesses Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment