From: H.J. Lu Date: Sat, 13 Sep 2025 01:52:39 +0000 (-0700) Subject: c/c++: Declare stack protection guard as a global symbol X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c05b5e5d8cb660ed43159d66fd669c20746d6bea;p=thirdparty%2Fgcc.git c/c++: Declare stack protection guard as a global symbol Add a new target hook, stack_protect_guard_symbol_p, to support the user provided stack protection guard as a global symbol. If the hook returns true, 1. Declare __stack_chk_guard as a global uintptr_t variable so that it can be initialized as an integer. 2. If the user declared variable matches __stack_chk_guard, merge it with __stack_chk_guard, including its visibility attribute. gcc/ PR c/121911 * target.def (stack_protect_guard_symbol_p): New target hook. * targhooks.cc (default_stack_protect_guard): Use the type of uintptr_t, instead of ptr_type_node, if the stack_protect_guard_symbol_p hook returns true. * config/i386/i386.cc (ix86_stack_protect_guard_symbol_p): New. (TARGET_STACK_PROTECT_GUARD_SYMBOL_P): Likewise. * doc/tm.texi: Regenerated. * doc/tm.texi.in (TARGET_STACK_PROTECT_GUARD_SYMBOL_P): New. gcc/c-family/ PR c/121911 * c-common.cc (c_common_nodes_and_builtins): If the stack_protect_guard_symbol_p hook returns true, declare a global symbol for stack protection guard. 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-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. * gcc.target/i386/ssp-global.c: Include . (__stack_chk_guard): Change its type to uintptr_t. Signed-off-by: H.J. Lu --- diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index dcbf5192fc1..2bf71e54045 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -4927,6 +4927,11 @@ c_common_nodes_and_builtins (void) } } + /* Call the target stack_protect_guard hook if the stack protection + guard is declared as a global symbol. */ + if (targetm.stack_protect_guard_symbol_p ()) + lang_hooks.decls.pushdecl (targetm.stack_protect_guard ()); + if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) { va_list_arg_type_node = va_list_ref_type_node = diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 15c2d631635..e73c2d7f7d0 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -25524,6 +25524,14 @@ ix86_stack_protect_guard (void) return default_stack_protect_guard (); } +/* Implement TARGET_STACK_PROTECT_GUARD_SYMBOL_P. */ + +static bool +ix86_stack_protect_guard_symbol_p (void) +{ + return TARGET_SSP_GLOBAL_GUARD; +} + static bool ix86_stack_protect_runtime_enabled_p (void) { @@ -28539,6 +28547,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_P +#define TARGET_STACK_PROTECT_GUARD_SYMBOL_P \ + ix86_stack_protect_guard_symbol_p + #undef TARGET_STACK_PROTECT_RUNTIME_ENABLED_P #define TARGET_STACK_PROTECT_RUNTIME_ENABLED_P \ ix86_stack_protect_runtime_enabled_p diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2832a447e3e..a4ae17decb0 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5426,6 +5426,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_P (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} with the @code{uintptr_t} type 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 274bb899d0c..1acda0c264c 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3825,6 +3825,8 @@ generic code. @hook TARGET_STACK_PROTECT_GUARD +@hook TARGET_STACK_PROTECT_GUARD_SYMBOL_P + @hook TARGET_STACK_PROTECT_FAIL @hook TARGET_STACK_PROTECT_RUNTIME_ENABLED_P diff --git a/gcc/target.def b/gcc/target.def index 11b358f4160..cdb3a6a6c84 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4654,6 +4654,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_p, + "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} with the @code{uintptr_t} type 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 5f1eac75122..295f70cb3f5 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -941,9 +941,12 @@ default_stack_protect_guard (void) { rtx x; + if (targetm.stack_protect_guard_symbol_p ()) + t = lang_hooks.types.type_for_mode (ptr_mode, 1); + 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; @@ -954,8 +957,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..5f4d64e3573 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/ssp-global-1.C @@ -0,0 +1,36 @@ +/* { dg-do run { target fstack_protector } } */ +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } */ + +#include +#include + +#ifdef __LP64__ +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; +#else +uintptr_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; +} 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..e0e2e7d7f9b --- /dev/null +++ b/gcc/testsuite/g++.target/i386/ssp-global-2.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-3.C b/gcc/testsuite/g++.target/i386/ssp-global-3.C new file mode 100644 index 00000000000..cc842b3d538 --- /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-hidden-1.C b/gcc/testsuite/g++.target/i386/ssp-global-hidden-1.C new file mode 100644 index 00000000000..dbb5732352c --- /dev/null +++ b/gcc/testsuite/g++.target/i386/ssp-global-hidden-1.C @@ -0,0 +1,45 @@ +/* { dg-do run { target { fstack_protector && fpic } } } */ +/* { dg-options "-O2 -fPIC -fstack-protector-all -mstack-protector-guard=global -save-temps" } */ + +#include +#include + +__attribute__ ((visibility ("hidden"))) +#ifdef __LP64__ +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; +#else +uintptr_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..9fd3b1d00d4 --- /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 + +extern uintptr_t __stack_chk_guard; +__attribute__ ((visibility ("hidden"))) +extern uintptr_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..e7b297f21ad --- /dev/null +++ b/gcc/testsuite/g++.target/i386/ssp-global-hidden-3.C @@ -0,0 +1,46 @@ +/* { dg-do run { target { fstack_protector && fpic } } } */ +/* { dg-options "-O2 -fPIC -mstack-protector-guard=global -save-temps" } */ + +#include +#include + +__attribute__ ((visibility ("hidden"))) +#ifdef __LP64__ +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; +#else +uintptr_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..760991f82bf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/ssp-global-2.c @@ -0,0 +1,36 @@ +/* { dg-do run { target fstack_protector } } */ +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } */ + +#include +#include + +#ifdef __LP64__ +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; +#else +uintptr_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; +} 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..dbccfb11311 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-1.c @@ -0,0 +1,45 @@ +/* { dg-do run { target { fstack_protector && fpic } } } */ +/* { dg-options "-O2 -fPIC -fstack-protector-all -mstack-protector-guard=global -save-temps" } */ + +#include +#include + +__attribute__ ((visibility ("hidden"))) +#ifdef __LP64__ +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; +#else +uintptr_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..9fd3b1d00d4 --- /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 + +extern uintptr_t __stack_chk_guard; +__attribute__ ((visibility ("hidden"))) +extern uintptr_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..d7ff2a252e1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-3.c @@ -0,0 +1,46 @@ +/* { dg-do run { target { fstack_protector && fpic } } } */ +/* { dg-options "-O2 -fPIC -mstack-protector-guard=global -save-temps" } */ + +#include +#include + +__attribute__ ((visibility ("hidden"))) +#ifdef __LP64__ +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; +#else +uintptr_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 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/ssp-global.c b/gcc/testsuite/gcc.target/i386/ssp-global.c index 85a288c781c..760991f82bf 100644 --- a/gcc/testsuite/gcc.target/i386/ssp-global.c +++ b/gcc/testsuite/gcc.target/i386/ssp-global.c @@ -1,12 +1,13 @@ /* { dg-do run { target fstack_protector } } */ /* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=global" } */ +#include #include #ifdef __LP64__ -const unsigned long int __stack_chk_guard = 0x2d853605a4d9a09cUL; +uintptr_t __stack_chk_guard = 0x2d853605a4d9a09cUL; #else -const unsigned long int __stack_chk_guard = 0xdd2cc927UL; +uintptr_t __stack_chk_guard = 0xdd2cc927UL; #endif void