On Sun, Oct 26, 2025 at 10:29:30AM +0800, H.J. Lu wrote:
> On Sat, Oct 25, 2025 at 4:42 PM H.J. Lu <[email protected]> wrote:
> ...
> > Here is the v4 patch.
> >
> > Add a new target hook, stack_protect_guard_symbol, to support the user
> > provided stack protection guard as an internal symbol.  If the hook is
> > true,
> >
> > 1. Make __stack_chk_guard an internal C/C++ symbol.
> > 2. Declare __stack_chk_guard as a size_t variable if size_t has the same
> > size as pointer so that it can be initialized as an integer.
> > 3. If the user declared variable matches __stack_chk_guard, merge it
> > with __stack_chk_guard, including its visibility attribute.
> > 4. Define the __stack_protection_guard_is_internal_symbol__ macro to
> > indicate that __stack_chk_guard is an internal symbol.
> >
> > gcc/
> >
> > PR c/121911
> > * target.def (stack_protect_guard_symbol): New target hook.
> > * targhooks.cc (default_stack_protect_guard): If
> > targetm.stack_protect_guard_symbol is true, make it an internal
> > symbol and use size_type_node if it has the same size as
> > ptr_type_node.
> > * tree.cc (build_common_tree_nodes): If stack protector is
> > enabled and targetm.stack_protect_guard_symbol is true, call
> > targetm.stack_protect_guard.
> > * config/i386/i386.cc (TARGET_STACK_PROTECT_GUARD_SYMBOL): New.
> > * doc/tm.texi: Regenerated.
> > * doc/tm.texi.in (TARGET_STACK_PROTECT_GUARD_SYMBOL): New.
> >
> > gcc/c-family/
> >
> > PR c/121911
> > * c-common.cc (matching_stack_protect_guard_decl_p): New.
> > * c-common.h (matching_stack_protect_guard_decl_p): Likewise.
> > * c-cppbuiltin.cc (c_cpp_builtins): Define the
> > __stack_protection_guard_is_internal_symbol__ macro if
> > targetm.stack_protect_guard_symbol is true.
> >
> > gcc/c/
> >
> > PR c/121911
> > * c-decl.cc: Include "c-family/c-common.h".
> > (merge_decls): Add a bool argument to keep the old type and copy
> > the old type if true.
> > (duplicate_decls): If the old decl is the stack protect guard and
> > the new decl matches the old decl, keep the type of the old decl.
> >
> > gcc/cp/
> >
> > PR c/121911
> > * decl.cc: Include "c-family/c-common.h".
> > (duplicate_decls): 2 types match if the old decl is the stack
> > protect guard and the new decl matches the old decl.
> >
> > gcc/testsuite/
> >
> > PR c/121911
> > * g++.target/i386/ssp-global-1.C: New test.
> > * g++.target/i386/ssp-global-2.C: Likewise.
> > * g++.target/i386/ssp-global-3.C: Likewise.
> > * g++.target/i386/ssp-global-4.C: Likewise.
> > * g++.target/i386/ssp-global-hidden-1.C: Likewise.
> > * g++.target/i386/ssp-global-hidden-2.C: Likewise.
> > * g++.target/i386/ssp-global-hidden-3.C: Likewise.
> > * gcc.target/i386/ssp-global-2.c: Likewise.
> > * gcc.target/i386/ssp-global-3.c: Likewise.
> > * gcc.target/i386/ssp-global-4.c: Likewise.
> > * gcc.target/i386/ssp-global-hidden-1.c: Likewise.
> > * gcc.target/i386/ssp-global-hidden-2.c: Likewise.
> > * gcc.target/i386/ssp-global-hidden-3.c: Likewise.
> >
> 
> Here is the v5 patch.  The main difference is that __stack_chk_guard
> is an internal symbol with C linkage now.
> 
> ---
> Add a new target hook, stack_protect_guard_symbol, to support the user
> provided stack protection guard as an internal symbol.  If the hook
> returns true,
> 
> 1. Make __stack_chk_guard an internal C/C++ symbol.
> 2. Declare __stack_chk_guard as a size_t variable if size_t has the same
> size as pointer so that it can be initialized as an integer.
> 3. If the user declared variable matches __stack_chk_guard, merge it
> with __stack_chk_guard, including its visibility attribute.
> 4. Define the __stack_protection_guard_is_internal_symbol__ macro to
> indicate that __stack_chk_guard is an internal symbol.
> 
> gcc/
> 
> PR c/121911
> * target.def (stack_protect_guard_symbol): New target hook.
> * targhooks.cc (default_stack_protect_guard): If the
> stack_protect_guard_symbol hook returns true, use size_type_node
> if it has the same size as ptr_type_node.
> * config/i386/i386.cc (ix86_stack_protect_guard_symbol): New.
> (TARGET_STACK_PROTECT_GUARD_SYMBOL): Likewise.
> * doc/tm.texi: Regenerated.
> * doc/tm.texi.in (TARGET_STACK_PROTECT_GUARD_SYMBOL): New.
> 
> gcc/c-family/
> 
> PR c/121911
> * c-common.cc (stack_protect_guard_decl): New.
> (pushing_stack_protect_guard_decl): Likewise.
> (c_stack_protect_guard_decl_p): Likewise.
> (duplicate_stack_protect_guard_decl_p): Likewise.
> (c_common_nodes_and_builtins): If the stack_protect_guard_symbol
> hook returns true, call targetm.stack_protect_guard.
> * c-common.h (c_stack_protect_guard_decl_p): New.
> (duplicate_stack_protect_guard_decl_p): Likewise.
> * c-cppbuiltin.cc (c_cpp_builtins): Define the
> __stack_protection_guard_is_internal_symbol__ macro if the
> stack_protect_guard_symbol hook returns.
> 
> gcc/c/
> 
> PR c/121911
> * c-decl.cc: Include "c-family/c-common.h".
> (merge_decls): Add a bool argument to keep the old type and copy
> the old type if true.
> (duplicate_decls): If the old decl is the stack protect guard and
> the new decl matches the old decl, keep the type of the old decl.
> 
> gcc/cp/
> 
> PR c/121911
> * cp-objcp-common.cc (cp_pushdecl): Change the stack protection
> guard symbol to C linkage.
> * decl.cc: Include "c-family/c-common.h".
> (duplicate_decls): 2 types match if the old decl is the stack
> protect guard and the new decl matches the old decl.
> 
> gcc/testsuite/
> 
> PR c/121911
> * g++.target/i386/ssp-global-1.C: New test.
> * g++.target/i386/ssp-global-2.C: Likewise.
> * g++.target/i386/ssp-global-3.C: Likewise.
> * g++.target/i386/ssp-global-4.C: Likewise.
> * g++.target/i386/ssp-global-hidden-1.C: Likewise.
> * g++.target/i386/ssp-global-hidden-2.C: Likewise.
> * g++.target/i386/ssp-global-hidden-3.C: Likewise.
> * gcc.target/i386/ssp-global-2.c: Likewise.
> * gcc.target/i386/ssp-global-3.c: Likewise.
> * gcc.target/i386/ssp-global-4.c: Likewise.
> * gcc.target/i386/ssp-global-hidden-1.c: Likewise.
> * gcc.target/i386/ssp-global-hidden-2.c: Likewise.
> * gcc.target/i386/ssp-global-hidden-3.c: Likewise.
> 
> 
> -- 
> H.J.

> From 6e23c0d75f5da0a41d33a4538debcf0649190a19 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <[email protected]>
> Date: Fri, 12 Sep 2025 18:52:39 -0700
> Subject: [PATCH v5] c/c++: Make stack protection guard an internal symbol
> 
> Add a new target hook, stack_protect_guard_symbol, to support the user
> provided stack protection guard as an internal symbol.  If the hook
> returns true,
> 
> 1. Make __stack_chk_guard an internal C/C++ symbol.
> 2. Declare __stack_chk_guard as a size_t variable if size_t has the same
> size as pointer so that it can be initialized as an integer.
> 3. If the user declared variable matches __stack_chk_guard, merge it
> with __stack_chk_guard, including its visibility attribute.
> 4. Define the __stack_protection_guard_is_internal_symbol__ macro to
> indicate that __stack_chk_guard is an internal symbol.
> 
> gcc/
> 
>       PR c/121911
>       * target.def (stack_protect_guard_symbol): New target hook.
>       * targhooks.cc (default_stack_protect_guard): If the
>       stack_protect_guard_symbol hook returns true, use size_type_node
>       if it has the same size as ptr_type_node.
>       * config/i386/i386.cc (ix86_stack_protect_guard_symbol): New.
>       (TARGET_STACK_PROTECT_GUARD_SYMBOL): Likewise.
>       * doc/tm.texi: Regenerated.
>       * doc/tm.texi.in (TARGET_STACK_PROTECT_GUARD_SYMBOL): New.
> 
> gcc/c-family/
> 
>       PR c/121911
>       * c-common.cc (stack_protect_guard_decl): New.
>       (pushing_stack_protect_guard_decl): Likewise.
>       (c_stack_protect_guard_decl_p): Likewise.
>       (duplicate_stack_protect_guard_decl_p): Likewise.
>       (c_common_nodes_and_builtins): If the stack_protect_guard_symbol
>       hook returns true, call targetm.stack_protect_guard.
>       * c-common.h (c_stack_protect_guard_decl_p): New.
>       (duplicate_stack_protect_guard_decl_p): Likewise.
>       * c-cppbuiltin.cc (c_cpp_builtins): Define the
>       __stack_protection_guard_is_internal_symbol__ macro if the
>       stack_protect_guard_symbol hook returns.
> 
> gcc/c/
> 
>       PR c/121911
>       * c-decl.cc: Include "c-family/c-common.h".
>       (merge_decls): Add a bool argument to keep the old type and copy
>       the old type if true.
>       (duplicate_decls): If the old decl is the stack protect guard and
>       the new decl matches the old decl, keep the type of the old decl.
> 
> gcc/cp/
> 
>       PR c/121911
>       * cp-objcp-common.cc (cp_pushdecl): Change the stack protection
>       guard symbol to C linkage.
>       * decl.cc: Include "c-family/c-common.h".
>       (duplicate_decls): 2 types match if the old decl is the stack
>       protect guard and the new decl matches the old decl.
> 
> gcc/testsuite/
> 
>       PR c/121911
>       * g++.target/i386/ssp-global-1.C: New test.
>       * g++.target/i386/ssp-global-2.C: Likewise.
>       * g++.target/i386/ssp-global-3.C: Likewise.
>       * g++.target/i386/ssp-global-4.C: Likewise.
>       * g++.target/i386/ssp-global-hidden-1.C: Likewise.
>       * g++.target/i386/ssp-global-hidden-2.C: Likewise.
>       * g++.target/i386/ssp-global-hidden-3.C: Likewise.
>       * gcc.target/i386/ssp-global-2.c: Likewise.
>       * gcc.target/i386/ssp-global-3.c: Likewise.
>       * gcc.target/i386/ssp-global-4.c: Likewise.
>       * gcc.target/i386/ssp-global-hidden-1.c: Likewise.
>       * gcc.target/i386/ssp-global-hidden-2.c: Likewise.
>       * gcc.target/i386/ssp-global-hidden-3.c: Likewise.
> 
> Signed-off-by: H.J. Lu <[email protected]>
> ---
>  gcc/c-family/c-common.cc                      | 48 +++++++++++++++++
>  gcc/c-family/c-common.h                       |  3 ++
>  gcc/c-family/c-cppbuiltin.cc                  |  5 ++
>  gcc/c/c-decl.cc                               | 22 +++++---
>  gcc/config/i386/i386.cc                       | 12 +++++
>  gcc/cp/cp-objcp-common.cc                     |  5 ++
>  gcc/cp/decl.cc                                |  6 ++-
>  gcc/doc/tm.texi                               |  7 +++
>  gcc/doc/tm.texi.in                            |  2 +
>  gcc/target.def                                | 11 ++++
>  gcc/targhooks.cc                              | 22 ++++++--
>  gcc/testsuite/g++.target/i386/ssp-global-1.C  | 35 +++++++++++++
>  gcc/testsuite/g++.target/i386/ssp-global-2.C  | 35 +++++++++++++
>  gcc/testsuite/g++.target/i386/ssp-global-3.C  |  4 ++
>  gcc/testsuite/g++.target/i386/ssp-global-4.C  |  4 ++
>  .../g++.target/i386/ssp-global-hidden-1.C     | 50 ++++++++++++++++++
>  .../g++.target/i386/ssp-global-hidden-2.C     | 20 ++++++++
>  .../g++.target/i386/ssp-global-hidden-3.C     | 51 +++++++++++++++++++
>  gcc/testsuite/gcc.target/i386/ssp-global-2.c  | 35 +++++++++++++
>  gcc/testsuite/gcc.target/i386/ssp-global-3.c  | 10 ++++
>  gcc/testsuite/gcc.target/i386/ssp-global-4.c  | 10 ++++
>  .../gcc.target/i386/ssp-global-hidden-1.c     | 49 ++++++++++++++++++
>  .../gcc.target/i386/ssp-global-hidden-2.c     | 20 ++++++++
>  .../gcc.target/i386/ssp-global-hidden-3.c     | 50 ++++++++++++++++++
>  24 files changed, 505 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-1.C
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-2.C
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-3.C
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-4.C
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-hidden-1.C
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-hidden-2.C
>  create mode 100644 gcc/testsuite/g++.target/i386/ssp-global-hidden-3.C
>  create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-2.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-3.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-4.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-hidden-1.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-hidden-2.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-hidden-3.c
> 
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index f2eed033706..b33b639c95c 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -299,6 +299,12 @@ bool in_late_binary_op;
>     cpp_finish (), we need to do so.  */
>  bool override_libcpp_locations;
>  
> +/* The stack protection guard.  */
> +static tree stack_protect_guard_decl;
> +
> +/* True if the stack protection guard is being pushed.  */
> +static bool pushing_stack_protect_guard_decl;
> +
>  /* Information about how a function name is generated.  */
>  struct fname_var_t
>  {
> @@ -4847,6 +4853,16 @@ c_common_nodes_and_builtins (void)
>       }
>      }
>  
> +  /* Call the target stack_protect_guard hook if the stack protection
> +     guard should be an internal symbol.  */
> +  if (targetm.stack_protect_guard_symbol ())

Maybe a matter of taste: since stack_protect_guard_symbol() does not
return an RTX symbol but is rather a predicate, maybe naming it
differently like sp_guard_internal_symbol_p or something along the lines
would make that more clear.

> +    {
> +      stack_protect_guard_decl = targetm.stack_protect_guard ();
> +      pushing_stack_protect_guard_decl = true;
> +      lang_hooks.decls.pushdecl (stack_protect_guard_decl);
> +      pushing_stack_protect_guard_decl = false;
> +    }
> +
>    if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
>      {
>        va_list_arg_type_node = va_list_ref_type_node =
> @@ -10592,4 +10608,36 @@ c_hardbool_type_attr_1 (tree type, tree 
> *false_value, tree *true_value)
>    return attr;
>  }
>  
> +/* Return true if DECL is the internal stack protection guard symbol.  */
> +
> +bool
> +c_stack_protect_guard_decl_p (tree decl)
> +{
> +  return (pushing_stack_protect_guard_decl
> +       || decl == stack_protect_guard_decl);
> +}
> +
> +/* Return true if for matched NEWDECL and OLDDECL, OLDDECL is the
> +   internal stack protection guard symbol.  */
> +
> +bool
> +duplicate_stack_protect_guard_decl_p (tree newdecl, tree olddecl)
> +{
> +  if (newdecl != error_mark_node
> +      && c_stack_protect_guard_decl_p (olddecl))
> +    {
> +      /* Allow different integer types with the same size.  */
> +      tree oldtype = TREE_TYPE (olddecl);
> +      tree newtype = TREE_TYPE (newdecl);
> +      if (TYPE_CANONICAL (newtype) == TYPE_CANONICAL (oldtype)
> +       || (TREE_CODE (newtype) == INTEGER_TYPE
> +           && TREE_CODE (oldtype) == INTEGER_TYPE
> +           && (TYPE_PRECISION (newtype)
> +               == TYPE_PRECISION (oldtype))))
> +     return true;
> +    }
> +
> +  return false;
> +}
> +
>  #include "gt-c-family-c-common.h"
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index bedbd4a94b0..a982058c6d0 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -1726,6 +1726,9 @@ extern bool compatible_types_for_indirection_note_p 
> (tree type1, tree type2);
>  
>  extern tree braced_lists_to_strings (tree, tree);
>  
> +extern bool c_stack_protect_guard_decl_p (tree);
> +extern bool duplicate_stack_protect_guard_decl_p (tree, tree);
> +
>  #if CHECKING_P
>  namespace selftest {
>    /* Declarations for specific families of tests within c-family,
> diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
> index 6b22f9e60b1..eaf11ffb6d0 100644
> --- a/gcc/c-family/c-cppbuiltin.cc
> +++ b/gcc/c-family/c-cppbuiltin.cc
> @@ -1191,6 +1191,11 @@ c_cpp_builtins (cpp_reader *pfile)
>       cpp_define (pfile, "__cpp_exceptions=199711L");
>      }
>  
> +  /* Define this to indicate that the stack protection guard symbol,
> +     "__stack_chk_guard", is an internal symbol.  */
> +  if (targetm.stack_protect_guard_symbol ())
> +    cpp_define (pfile, "__stack_protection_guard_is_internal_symbol__");
> +
>    /* Represents the C++ ABI version, always defined so it can be used while
>       preprocessing C and assembler.  */
>    if (flag_abi_version == 0)
> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> index 061892ac95b..f6b302087e6 100644
> --- a/gcc/c/c-decl.cc
> +++ b/gcc/c/c-decl.cc
> @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "attribs.h"
>  #include "toplev.h"
>  #include "debug.h"
> +#include "c-family/c-common.h"
>  #include "c-family/c-objc.h"
>  #include "c-family/c-pragma.h"
>  #include "c-family/c-ubsan.h"
> @@ -2743,7 +2744,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
>     diagnostics.  */
>  
>  static void
> -merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
> +merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype,
> +          bool keep_oldtype = false)
>  {
>    bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
>                           && DECL_INITIAL (newdecl) != NULL_TREE);
> @@ -2830,9 +2832,12 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, 
> tree oldtype)
>      }
>  
>    /* Merge the data types specified in the two decls.  */
> -  TREE_TYPE (newdecl)
> -    = TREE_TYPE (olddecl)
> -    = composite_type (newtype, oldtype);
> +  if (keep_oldtype)
> +    TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
> +  else
> +    TREE_TYPE (newdecl)
> +      = TREE_TYPE (olddecl)
> +      = composite_type (newtype, oldtype);
>  
>    /* Lay the type out, unless already done.  */
>    if (!comptypes (oldtype, TREE_TYPE (newdecl)))
> @@ -3206,8 +3211,13 @@ static bool
>  duplicate_decls (tree newdecl, tree olddecl)
>  {
>    tree newtype = NULL, oldtype = NULL;
> +  bool keep_oldtype = false;
>  
> -  if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
> +  /* Keep the internal stack protection guard type.  */
> +  if (duplicate_stack_protect_guard_decl_p (newdecl, olddecl))
> +    keep_oldtype = true;
> +  else if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype,
> +                                    &oldtype))
>      {
>        /* Avoid `unused variable' and other warnings for OLDDECL.  */
>        suppress_warning (olddecl, OPT_Wunused);
> @@ -3225,7 +3235,7 @@ duplicate_decls (tree newdecl, tree olddecl)
>        return false;
>      }
>  
> -  merge_decls (newdecl, olddecl, newtype, oldtype);
> +  merge_decls (newdecl, olddecl, newtype, oldtype, keep_oldtype);
>  
>    /* The NEWDECL will no longer be needed.
>  
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index 587b2bd0c1d..0d35d9bd120 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -25221,6 +25221,14 @@ ix86_stack_protect_guard (void)
>    return default_stack_protect_guard ();
>  }
>  
> +/* Implement TARGET_STACK_PROTECT_GUARD_SYMBOL.  */
> +
> +static bool
> +ix86_stack_protect_guard_symbol (void)
> +{
> +  return TARGET_SSP_GLOBAL_GUARD;
> +}
> +
>  static bool
>  ix86_stack_protect_runtime_enabled_p (void)
>  {
> @@ -28162,6 +28170,10 @@ ix86_libgcc_floating_mode_supported_p
>  #undef TARGET_STACK_PROTECT_GUARD
>  #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard
>  
> +#undef TARGET_STACK_PROTECT_GUARD_SYMBOL
> +#define TARGET_STACK_PROTECT_GUARD_SYMBOL \
> +  ix86_stack_protect_guard_symbol
> +
>  #undef TARGET_STACK_PROTECT_RUNTIME_ENABLED_P
>  #define TARGET_STACK_PROTECT_RUNTIME_ENABLED_P \
>    ix86_stack_protect_runtime_enabled_p
> diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
> index c7e88cb7bfe..d6363f8d0b4 100644
> --- a/gcc/cp/cp-objcp-common.cc
> +++ b/gcc/cp/cp-objcp-common.cc
> @@ -521,6 +521,11 @@ tree
>  cp_pushdecl (tree decl)
>  {
>    DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
> +  if (c_stack_protect_guard_decl_p (decl))
> +    {
> +      retrofit_lang_decl (decl);
> +      SET_DECL_LANGUAGE (decl, lang_c);
> +    }
>    return pushdecl (decl);
>  }
>  
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 2089e4c21ac..1dde1ef4af5 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "decl.h"
>  #include "intl.h"
>  #include "toplev.h"
> +#include "c-family/c-common.h"
>  #include "c-family/c-objc.h"
>  #include "c-family/c-pragma.h"
>  #include "c-family/c-ubsan.h"
> @@ -1805,7 +1806,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
> hiding, bool was_hidden)
>    if (newdecl == olddecl)
>      return olddecl;
>  
> -  types_match = decls_match (newdecl, olddecl);
> +  if (duplicate_stack_protect_guard_decl_p (newdecl, olddecl))
> +    types_match = 1;
> +  else
> +    types_match = decls_match (newdecl, olddecl);
>  
>    /* If either the type of the new decl or the type of the old decl is an
>       error_mark_node, then that implies that we have already issued an
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index fd208f53844..ab1ce3805a6 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -5408,6 +5408,13 @@ The default version of this hook creates a variable 
> called
>  @samp{__stack_chk_guard}, which is normally defined in @file{libgcc2.c}.
>  @end deftypefn
>  
> +@deftypefn {Target Hook} bool TARGET_STACK_PROTECT_GUARD_SYMBOL (void)
> +Usually, the compiler uses an external variable @samp{__stack_chk_guard}
> +defined in @file{libgcc2.c} as the stack protection guard symbol.  Define
> +this hook to return true if a user provided definition of
> +@samp{__stack_chk_guard} is used.
> +@end deftypefn
> +
>  @deftypefn {Target Hook} tree TARGET_STACK_PROTECT_FAIL (void)
>  This hook returns a @code{CALL_EXPR} that alerts the runtime that the
>  stack protect guard variable has been modified.  This expression should
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index 14315dd5080..2db947e3afd 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -3808,6 +3808,8 @@ generic code.
>  
>  @hook TARGET_STACK_PROTECT_GUARD
>  
> +@hook TARGET_STACK_PROTECT_GUARD_SYMBOL
> +
>  @hook TARGET_STACK_PROTECT_FAIL
>  
>  @hook TARGET_STACK_PROTECT_RUNTIME_ENABLED_P
> diff --git a/gcc/target.def b/gcc/target.def
> index f288329ffca..fa5e4c42410 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -4637,6 +4637,17 @@ The default version of this hook creates a variable 
> called\n\
>   tree, (void),
>   default_stack_protect_guard)
>  
> +/* Return true if the user provided stack protection guard definition of
> +   __stack_chk_guard is used.  */
> +DEFHOOK
> +(stack_protect_guard_symbol,
> + "Usually, the compiler uses an external variable @samp{__stack_chk_guard}\n\
> +defined in @file{libgcc2.c} as the stack protection guard symbol.  Define\n\
> +this hook to return true if a user provided definition of\n\
> +@samp{__stack_chk_guard} is used.",
> + bool, (void),
> + hook_bool_void_false)
> +
>  /* This target hook allows the operating system to override the CALL_EXPR
>     that is invoked when a check vs the guard variable fails.  */
>  DEFHOOK
> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
> index 1873d572ba3..326100cc59f 100644
> --- a/gcc/targhooks.cc
> +++ b/gcc/targhooks.cc
> @@ -924,9 +924,17 @@ default_stack_protect_guard (void)
>      {
>        rtx x;
>  
> +      /* If __stack_chk_guard is an internal symbol, use size_type_node
> +      if it has the same size as ptr_type_node so that the guard
> +      symbol can be initialized as an integer.  */
> +      if (targetm.stack_protect_guard_symbol ()
> +       && (TYPE_PRECISION (size_type_node)
> +           == TYPE_PRECISION (ptr_type_node)))
> +     t = size_type_node;
> +      else
> +     t = ptr_type_node;
>        t = build_decl (UNKNOWN_LOCATION,
> -                   VAR_DECL, get_identifier ("__stack_chk_guard"),
> -                   ptr_type_node);
> +                   VAR_DECL, get_identifier ("__stack_chk_guard"), t);
>        TREE_STATIC (t) = 1;
>        TREE_PUBLIC (t) = 1;
>        DECL_EXTERNAL (t) = 1;
                          ~~~^
Shouldn't this be also changed?  Maybe something like

      bool is_internal = targetm.stack_protect_guard_symbol ()
        && (TYPE_PRECISION (size_type_node) == TYPE_PRECISION (ptr_type_node));
      if (is_internal)
        t = size_type_node;
      else
        t = ptr_type_node;
      ...
      DECL_EXTERNAL (t) = !is_internal;

Cheers,
Stefan

> @@ -937,8 +945,14 @@ default_stack_protect_guard (void)
>  
>        /* Do not share RTL as the declaration is visible outside of
>        current function.  */
> -      x = DECL_RTL (t);
> -      RTX_FLAG (x, used) = 1;
> +      if (mode_mem_attrs[(int) DECL_MODE (t)])
> +     {
> +       /* NB: Don't call make_decl_rtl when mode_mem_attrs isn't
> +          initialized.  -save-temps won't initialize mode_mem_attrs
> +          and make_decl_rtl will fail.  */
> +       x = DECL_RTL (t);
> +       RTX_FLAG (x, used) = 1;
> +     }
>  
>        stack_chk_guard_decl = t;
>      }
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-1.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-1.C
> new file mode 100644
> index 00000000000..086a0a1d9ae
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-1.C
> @@ -0,0 +1,35 @@
> +/* { dg-do run { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +#include <stdlib.h>
> +
> +#ifdef __LP64__
> +const unsigned long int __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +const unsigned long int __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +extern "C" void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-2.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-2.C
> new file mode 100644
> index 00000000000..9ae28f554c9
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-2.C
> @@ -0,0 +1,35 @@
> +/* { dg-do run { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +#include <stdlib.h>
> +
> +#ifdef __LP64__
> +long int __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +int __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +extern "C" void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-3.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-3.C
> new file mode 100644
> index 00000000000..e0e2e7d7f9b
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-3.C
> @@ -0,0 +1,4 @@
> +/* { dg-do compile { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +extern char *__stack_chk_guard; /* { dg-error "conflicting declaration 
> 'char. __stack_chk_guard'" } */
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-4.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-4.C
> new file mode 100644
> index 00000000000..cc842b3d538
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-4.C
> @@ -0,0 +1,4 @@
> +/* { dg-do compile { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +extern char __stack_chk_guard; /* { dg-error "conflicting declaration 'char 
> __stack_chk_guard'" } */
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-hidden-1.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-hidden-1.C
> new file mode 100644
> index 00000000000..7d203a35309
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-hidden-1.C
> @@ -0,0 +1,50 @@
> +/* { dg-do run { target { fstack_protector && fpic } } } */
> +/* { dg-options "-O2 -fPIC -fstack-protector-all 
> -mstack-protector-guard=global -save-temps" } */
> +
> +#ifndef __stack_protection_guard_is_internal_symbol__
> +# error "__stack_protection_guard_is_internal_symbol__ isn't defined"
> +#endif
> +
> +#include <stdlib.h>
> +#include <stddef.h>
> +
> +extern "C"
> +__attribute__ ((visibility ("hidden")))
> +#ifdef __LP64__
> +const size_t __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +const size_t __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +extern "C" void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> +
> +/* { dg-final { scan-hidden "__stack_chk_guard" } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard\\(%rip\\)" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOTPCREL" { target { ! 
> ia32 } } } } */
> +  /* { dg-final { scan-assembler ".quad      3280087301477736604" { target { 
> lp64 } } } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard@GOTOFF" { target ia32 } } 
> } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOT\\(" { target ia32 
> } } } */
> +  /* { dg-final { scan-assembler ".long      -584267481" { target { ! lp64 } 
> } } } */
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-hidden-2.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-hidden-2.C
> new file mode 100644
> index 00000000000..8b4e806edf1
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-hidden-2.C
> @@ -0,0 +1,20 @@
> +/* { dg-do compile { target { fstack_protector && fpic } } } */
> +/* { dg-options "-O2 -fPIC -fstack-protector-all 
> -mstack-protector-guard=global" } */
> +
> +#include <stddef.h>
> +
> +extern const size_t __stack_chk_guard;
> +__attribute__ ((visibility ("hidden")))
> +extern const size_t __stack_chk_guard;
> +
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +/* { dg-final { scan-hidden "__stack_chk_guard" } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard\\(%rip\\)" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOTPCREL" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard@GOTOFF" { target ia32 } } 
> } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOT\\(" { target ia32 
> } } } */
> diff --git a/gcc/testsuite/g++.target/i386/ssp-global-hidden-3.C 
> b/gcc/testsuite/g++.target/i386/ssp-global-hidden-3.C
> new file mode 100644
> index 00000000000..ca0508cac1d
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/ssp-global-hidden-3.C
> @@ -0,0 +1,51 @@
> +/* { dg-do run { target { fstack_protector && fpic } } } */
> +/* { dg-options "-O2 -fPIC -mstack-protector-guard=global -save-temps" } */
> +
> +#ifndef __stack_protection_guard_is_internal_symbol__
> +# error "__stack_protection_guard_is_internal_symbol__ isn't defined"
> +#endif
> +
> +#include <stdlib.h>
> +#include <stddef.h>
> +
> +extern "C"
> +__attribute__ ((visibility ("hidden")))
> +#ifdef __LP64__
> +const size_t __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +const size_t __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +extern "C" void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +__attribute__ ((optimize ("stack-protector-all")))
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> +
> +/* { dg-final { scan-hidden "__stack_chk_guard" } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard\\(%rip\\)" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOTPCREL" { target { ! 
> ia32 } } } } */
> +  /* { dg-final { scan-assembler ".quad      3280087301477736604" { target { 
> lp64 } } } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard@GOTOFF" { target ia32 } } 
> } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOT\\(" { target ia32 
> } } } */
> +  /* { dg-final { scan-assembler ".long      -584267481" { target { ! lp64 } 
> } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/ssp-global-2.c 
> b/gcc/testsuite/gcc.target/i386/ssp-global-2.c
> new file mode 100644
> index 00000000000..11b69909327
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ssp-global-2.c
> @@ -0,0 +1,35 @@
> +/* { dg-do run { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +#include <stdlib.h>
> +
> +#ifdef __LP64__
> +long int __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +int __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/ssp-global-3.c 
> b/gcc/testsuite/gcc.target/i386/ssp-global-3.c
> new file mode 100644
> index 00000000000..b276e3f5833
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ssp-global-3.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +extern char *__stack_chk_guard; /* { dg-error "conflicting types for 
> '__stack_chk_guard';" } */
> +
> +char
> +foo (void)
> +{
> +  return *__stack_chk_guard;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/ssp-global-4.c 
> b/gcc/testsuite/gcc.target/i386/ssp-global-4.c
> new file mode 100644
> index 00000000000..cf375b704f2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ssp-global-4.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile { target fstack_protector } } */
> +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } 
> */
> +
> +extern char __stack_chk_guard; /* { dg-error "conflicting types for 
> '__stack_chk_guard';" } */
> +
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/ssp-global-hidden-1.c 
> b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-1.c
> new file mode 100644
> index 00000000000..092d68f049c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-1.c
> @@ -0,0 +1,49 @@
> +/* { dg-do run { target { fstack_protector && fpic } } } */
> +/* { dg-options "-O2 -fPIC -fstack-protector-all 
> -mstack-protector-guard=global -save-temps" } */
> +
> +#ifndef __stack_protection_guard_is_internal_symbol__
> +# error "__stack_protection_guard_is_internal_symbol__ isn't defined"
> +#endif
> +
> +#include <stdlib.h>
> +#include <stddef.h>
> +
> +__attribute__ ((visibility ("hidden")))
> +#ifdef __LP64__
> +const size_t __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +const size_t __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> +
> +/* { dg-final { scan-hidden "__stack_chk_guard" } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard\\(%rip\\)" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOTPCREL" { target { ! 
> ia32 } } } } */
> +  /* { dg-final { scan-assembler ".quad      3280087301477736604" { target { 
> lp64 } } } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard@GOTOFF" { target ia32 } } 
> } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOT\\(" { target ia32 
> } } } */
> +  /* { dg-final { scan-assembler ".long      -584267481" { target { ! lp64 } 
> } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/ssp-global-hidden-2.c 
> b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-2.c
> new file mode 100644
> index 00000000000..8b4e806edf1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-2.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile { target { fstack_protector && fpic } } } */
> +/* { dg-options "-O2 -fPIC -fstack-protector-all 
> -mstack-protector-guard=global" } */
> +
> +#include <stddef.h>
> +
> +extern const size_t __stack_chk_guard;
> +__attribute__ ((visibility ("hidden")))
> +extern const size_t __stack_chk_guard;
> +
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +/* { dg-final { scan-hidden "__stack_chk_guard" } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard\\(%rip\\)" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOTPCREL" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard@GOTOFF" { target ia32 } } 
> } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOT\\(" { target ia32 
> } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/ssp-global-hidden-3.c 
> b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-3.c
> new file mode 100644
> index 00000000000..f73856c581f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-3.c
> @@ -0,0 +1,50 @@
> +/* { dg-do run { target { fstack_protector && fpic } } } */
> +/* { dg-options "-O2 -fPIC -mstack-protector-guard=global -save-temps" } */
> +
> +#ifndef __stack_protection_guard_is_internal_symbol__
> +# error "__stack_protection_guard_is_internal_symbol__ isn't defined"
> +#endif
> +
> +#include <stdlib.h>
> +#include <stddef.h>
> +
> +__attribute__ ((visibility ("hidden")))
> +#ifdef __LP64__
> +const size_t __stack_chk_guard = 0x2d853605a4d9a09cUL;
> +#else
> +const size_t __stack_chk_guard = 0xdd2cc927UL;
> +#endif
> +
> +void
> +__stack_chk_fail (void)
> +{
> +  exit (0); /* pass */
> +}
> +
> +__attribute__ ((noipa))
> +void
> +smash (char *p, int i)
> +{
> +  p[i] = 42;
> +}
> +
> +__attribute__ ((optimize ("stack-protector-all")))
> +int
> +main (void)
> +{
> +  char foo[255];
> +
> +   /* smash stack */
> +  for (int i = 0; i <= 400; i++)
> +    smash (foo, i);
> +
> +  return 1;
> +}
> +
> +/* { dg-final { scan-hidden "__stack_chk_guard" } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard\\(%rip\\)" { target { ! 
> ia32 } } } } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOTPCREL" { target { ! 
> ia32 } } } } */
> +  /* { dg-final { scan-assembler ".quad      3280087301477736604" { target { 
> lp64 } } } } */
> +/* { dg-final { scan-assembler "__stack_chk_guard@GOTOFF" { target ia32 } } 
> } */
> +/* { dg-final { scan-assembler-not "__stack_chk_guard@GOT\\(" { target ia32 
> } } } */
> +  /* { dg-final { scan-assembler ".long      -584267481" { target { ! lp64 } 
> } } } */
> -- 
> 2.51.0
> 

Reply via email to