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 ())
+    {
+      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;
@@ -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