Treat the user defined stack protect guard, __stack_chk_guard, as an internal C/C++ symbol and declare __stack_chk_guard as a size_t variable if size_t has the same size as pointer. If a user defined variable name is the same as the stack protect guard, use the predefined stack protect guard declaration and apply its visibility attribute to the internal __stack_chk_guard symbol.
gcc/ PR c/121911 * targhooks.cc (default_stack_protect_guard): Use size_type_node if it has the same size as ptr_type_node. * varasm.cc (mark_stack_protect_guard_decl_local): New. * varasm.h (mark_stack_protect_guard_decl_local): Likewise. gcc/c-family/ PR c/121911 * c-attribs.cc (handle_visibility_attribute): Call mark_stack_protect_guard_decl_local as local for non-default visibility. gcc/c/ PR c/121911 * c-decl.cc (grokdeclarator): If the variable name is the same as the stack protect guard, use the stack protect guard decl. gcc/cp/ PR c/121911 * decl.cc (grokdeclarator): If the variable name is the same as the stack protect guard, use the stack protect guard decl. gcc/testsuite/ PR c/121911 * g++.target/i386/ssp-global-hidden-1.C: New test. * g++.target/i386/ssp-global-hidden-2.C: Likewise. * gcc.target/i386/ssp-global-hidden-1.c: Likewise. * gcc.target/i386/ssp-global-hidden-2.c: Likewise. Signed-off-by: H.J. Lu <hjl.to...@gmail.com> --- gcc/c-family/c-attribs.cc | 5 +++ gcc/c/c-decl.cc | 16 +++++++ gcc/cp/decl.cc | 15 +++++++ gcc/targhooks.cc | 7 ++- .../g++.target/i386/ssp-global-hidden-1.C | 45 +++++++++++++++++++ .../g++.target/i386/ssp-global-hidden-2.C | 19 ++++++++ .../gcc.target/i386/ssp-global-hidden-1.c | 45 +++++++++++++++++++ .../gcc.target/i386/ssp-global-hidden-2.c | 19 ++++++++ gcc/varasm.cc | 12 +++++ gcc/varasm.h | 1 + 10 files changed, 183 insertions(+), 1 deletion(-) 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/gcc.target/i386/ssp-global-hidden-1.c create mode 100644 gcc/testsuite/gcc.target/i386/ssp-global-hidden-2.c diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 1e3a94ed949..8d76e81bf98 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -3652,6 +3652,11 @@ handle_visibility_attribute (tree *node, tree name, tree args, DECL_VISIBILITY (decl) = vis; DECL_VISIBILITY_SPECIFIED (decl) = 1; + /* Mark the symbol of DECL for non-default visibility as local if it + is the stack protect guard decl. */ + if (flag_stack_protect && vis != VISIBILITY_DEFAULT) + mark_stack_protect_guard_decl_local (decl); + /* Go ahead and attach the attribute to the node as well. This is needed so we can determine whether we have VISIBILITY_DEFAULT because the visibility was not specified, or because it was explicitly overridden diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index b122e82bfc4..89885593acc 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -8106,6 +8106,22 @@ grokdeclarator (const struct c_declarator *declarator, else { /* It's a variable. */ + + if (flag_stack_protect) + { + /* If the variable name is the same as the stack protect + guard, use the stack protect guard decl. */ + tree guard_decl = targetm.stack_protect_guard (); + if (guard_decl && VAR_P (guard_decl)) + { + const char *stack_protect_guard_name + = IDENTIFIER_POINTER (DECL_NAME (guard_decl)); + if (strcmp (stack_protect_guard_name, + IDENTIFIER_POINTER (declarator->u.id.id)) == 0) + return guard_decl; + } + } + /* An uninitialized decl with `extern' is a reference. */ int extern_ref = !initialized && storage_class == csc_extern; diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index a6a98426ed9..2e6e935bcc9 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -16233,6 +16233,21 @@ grokdeclarator (const cp_declarator *declarator, { /* It's a variable. */ + if (flag_stack_protect && dname && identifier_p (dname)) + { + /* If the variable name is the same as the stack protect + guard, use the stack protect guard decl. */ + tree guard_decl = targetm.stack_protect_guard (); + if (guard_decl && VAR_P (guard_decl)) + { + const char *stack_protect_guard_name + = IDENTIFIER_POINTER (DECL_NAME (guard_decl)); + if (strcmp (stack_protect_guard_name, + IDENTIFIER_POINTER (unqualified_id)) == 0) + return guard_decl; + } + } + /* An uninitialized decl with `extern' is a reference. */ decl = grokvardecl (type, dname, unqualified_id, declspecs, diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index 947e39aedc1..fc24a6fd488 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -924,9 +924,14 @@ default_stack_protect_guard (void) { rtx x; + /* __stack_chk_guard is treated as an internal C/C++ symbol. Use + size_type_node if it has the same size as ptr_type_node since + __stack_chk_guard can be initialized as an integer. */ t = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier ("__stack_chk_guard"), - ptr_type_node); + (TYPE_PRECISION (size_type_node) + == TYPE_PRECISION (ptr_type_node) + ? size_type_node : ptr_type_node)); TREE_STATIC (t) = 1; TREE_PUBLIC (t) = 1; DECL_EXTERNAL (t) = 1; 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..2f7a554ccbd --- /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 <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 + +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..845cf550eb9 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/ssp-global-hidden-2.C @@ -0,0 +1,19 @@ +/* { dg-do compile { target { fstack_protector && fpic } } } */ +/* { dg-options "-O2 -fPIC -fstack-protector-all -mstack-protector-guard=global" } */ + +#include <stddef.h> + +__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-1.c b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-1.c new file mode 100644 index 00000000000..cf6af3971d7 --- /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 <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..845cf550eb9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/ssp-global-hidden-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { fstack_protector && fpic } } } */ +/* { dg-options "-O2 -fPIC -fstack-protector-all -mstack-protector-guard=global" } */ + +#include <stddef.h> + +__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/varasm.cc b/gcc/varasm.cc index 0d78f5b384f..5b54293dc1e 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -2920,6 +2920,18 @@ mark_decl_referenced (tree decl) which do not need to be marked. */ } +/* Mark the symbol of DECL as local if it is the stack protect guard + decl. */ + +void +mark_stack_protect_guard_decl_local (tree decl) +{ + if (decl != targetm.stack_protect_guard ()) + return; + rtx symbol = DECL_RTL (decl); + symbol = XEXP (symbol, 0); + SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL; +} /* Output to FILE (an assembly file) a reference to NAME. If NAME starts with a *, the rest of NAME is output verbatim. Otherwise diff --git a/gcc/varasm.h b/gcc/varasm.h index fc31c1bbf65..33171999496 100644 --- a/gcc/varasm.h +++ b/gcc/varasm.h @@ -41,6 +41,7 @@ extern void process_pending_assemble_externals (void); extern bool decl_replaceable_p (tree, bool); extern bool decl_binds_to_current_def_p (const_tree); extern enum tls_model decl_default_tls_model (const_tree); +extern void mark_stack_protect_guard_decl_local (tree); /* Declare DECL to be a weak symbol. */ extern void declare_weak (tree); -- 2.51.0