Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 250999) +++ config/i386/i386.c (working copy) @@ -45858,6 +45858,8 @@ ix86_mangle_type (const_tree type) } } +static GTY(()) tree ix86_tls_stack_chk_guard_decl; + static tree ix86_stack_protect_guard (void) { @@ -45864,15 +45866,47 @@ ix86_stack_protect_guard (void) if (TARGET_SSP_TLS_GUARD) { tree type_node = lang_hooks.types.type_for_mode (ptr_mode, 1); - int qual = ENCODE_QUAL_ADDR_SPACE (ix86_stack_protector_guard_reg); + tree type = build_qualified_type (type_node, qual); + tree t; - tree type = build_qualified_type (type_node, qual); - tree asptrtype = build_pointer_type (type); - tree sspoff = build_int_cst (asptrtype, - ix86_stack_protector_guard_offset); - tree t = build2 (MEM_REF, asptrtype, sspoff, - build_int_cst (asptrtype, 0)); + if (global_options_set.x_ix86_stack_protector_guard_symbol_str) + { + t = ix86_tls_stack_chk_guard_decl; + + if (t == NULL) + { + rtx x; + + t = build_decl + (UNKNOWN_LOCATION, VAR_DECL, + get_identifier (ix86_stack_protector_guard_symbol_str), + type); + TREE_STATIC (t) = 1; + TREE_PUBLIC (t) = 1; + DECL_EXTERNAL (t) = 1; + TREE_USED (t) = 1; + TREE_THIS_VOLATILE (t) = 1; + DECL_ARTIFICIAL (t) = 1; + DECL_IGNORED_P (t) = 1; + + /* Do not share RTL as the declaration is visible outside of + current function. */ + x = DECL_RTL (t); + RTX_FLAG (x, used) = 1; + + ix86_tls_stack_chk_guard_decl = t; + } + } + else + { + tree asptrtype = build_pointer_type (type); + + t = build_int_cst (asptrtype, ix86_stack_protector_guard_offset); + t = build2 (MEM_REF, asptrtype, t, + build_int_cst (asptrtype, 0)); + } + return t; } Index: config/i386/i386.opt =================================================================== --- config/i386/i386.opt (revision 250999) +++ config/i386/i386.opt (working copy) @@ -938,6 +938,10 @@ Use the given offset for addressing the stack-prot TargetVariable HOST_WIDE_INT ix86_stack_protector_guard_offset = 0 +mstack-protector-guard-symbol= +Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_symbol_str) +Use the given symbol for addressing the stack-protector guard. + mmitigate-rop Target Var(flag_mitigate_rop) Init(0) Attempt to avoid generating instruction sequences containing ret bytes. Index: doc/invoke.texi =================================================================== --- doc/invoke.texi (revision 250999) +++ doc/invoke.texi (working copy) @@ -1216,7 +1216,8 @@ See RS/6000 and PowerPC Options. -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol -mstack-protector-guard-reg=@var{reg} @gol --mstack-protector-guard-offset=@var{offset} -mmitigate-rop @gol +-mstack-protector-guard-offset=@var{offset} @gol +-mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol -mgeneral-regs-only -mcall-ms2sysv-xlogues} @emph{x86 Windows Options} @@ -22753,9 +22754,11 @@ The @option{-mno-compat-align-parm} option is the @item -mstack-protector-guard=@var{guard} @itemx -mstack-protector-guard-reg=@var{reg} @itemx -mstack-protector-guard-offset=@var{offset} +@itemx -mstack-protector-guard-symbol=@var{symbol} @opindex mstack-protector-guard @opindex mstack-protector-guard-reg @opindex mstack-protector-guard-offset +@opindex mstack-protector-guard-symbol 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). @@ -22765,7 +22768,8 @@ With the latter choice the options @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. +relevant ABI. @option{-mstack-protector-guard-symbol=@var{symbol}} overrides +the offset with a symbol reference to a canary in the TLS block. @end table @node RX Options Index: testsuite/gcc.target/i386/stack-prot-sym.c =================================================================== --- testsuite/gcc.target/i386/stack-prot-sym.c (nonexistent) +++ testsuite/gcc.target/i386/stack-prot-sym.c (working copy) @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=tls -mstack-protector-guard-reg=gs -mstack-protector-guard-symbol=my_guard" } */ + +void f(void) { } + +/* { dg-final { scan-assembler "gs:my_guard" } } */