diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2015-09-10 10:56:36 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2015-09-10 10:56:36 +0000 |
commit | c6eebf721ef39cd501b72356dcfcc517ac3da9bc (patch) | |
tree | 6c57aa5062b779e31c3084f649a3de49d2bf6fbf /gnu | |
parent | fe229282140b36bac29b62e9f1d2dc4cd8acfb1b (diff) |
Makde gcc handle __stack_smash_handler similarly to memcpy and memset when
creating calls: cache the RTL, let a declaration alter the asm spec, and
set the same RTL attributes. For all three, let a declaration set the ELF
visibility.
ok miod@
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/gcc/gcc/c-common.c | 4 | ||||
-rw-r--r-- | gnu/gcc/gcc/c-decl.c | 24 | ||||
-rw-r--r-- | gnu/gcc/gcc/expr.c | 18 | ||||
-rw-r--r-- | gnu/gcc/gcc/expr.h | 5 | ||||
-rw-r--r-- | gnu/gcc/gcc/targhooks.c | 59 |
5 files changed, 71 insertions, 39 deletions
diff --git a/gnu/gcc/gcc/c-common.c b/gnu/gcc/gcc/c-common.c index 68db97e8c05..be20dd52c65 100644 --- a/gnu/gcc/gcc/c-common.c +++ b/gnu/gcc/gcc/c-common.c @@ -3416,9 +3416,9 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec) builtin = built_in_decls [DECL_FUNCTION_CODE (decl)]; set_user_assembler_name (builtin, asmspec); if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY) - init_block_move_fn (asmspec); + init_block_move_fn (decl, asmspec); else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET) - init_block_clear_fn (asmspec); + init_block_clear_fn (decl, asmspec); } /* The number of named compound-literals generated thus far. */ diff --git a/gnu/gcc/gcc/c-decl.c b/gnu/gcc/gcc/c-decl.c index 042a2e1291c..f09ffd96a04 100644 --- a/gnu/gcc/gcc/c-decl.c +++ b/gnu/gcc/gcc/c-decl.c @@ -3484,16 +3484,6 @@ finish_decl (tree decl, tree init, tree asmspec_tree) TREE_USED (decl) = 1; } - /* If this is a function and an assembler name is specified, reset DECL_RTL - so we can give it its new name. Also, update built_in_decls if it - was a normal built-in. */ - if (TREE_CODE (decl) == FUNCTION_DECL && asmspec) - { - if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) - set_builtin_user_assembler_name (decl, asmspec); - set_user_assembler_name (decl, asmspec); - } - /* If #pragma weak was used, mark the decl weak now. */ maybe_apply_pragma_weak (decl); @@ -3513,12 +3503,24 @@ finish_decl (tree decl, tree init, tree asmspec_tree) if (asmspec) { + /* If this is a function and an assembler name is specified, + reset DECL_RTL so we can give it its new name. Also, + update built_in_decls if it was a normal built-in. */ + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) + set_builtin_user_assembler_name (decl, asmspec); + else if (strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), + "__stack_smash_handler") == 0) + init_stack_smash_fn (decl, asmspec); + set_user_assembler_name (decl, asmspec); + } /* If this is not a static variable, issue a warning. It doesn't make any sense to give an ASMSPEC for an ordinary, non-register local variable. Historically, GCC has accepted -- but ignored -- the ASMSPEC in this case. */ - if (!DECL_FILE_SCOPE_P (decl) + else if (!DECL_FILE_SCOPE_P (decl) && TREE_CODE (decl) == VAR_DECL && !C_DECL_REGISTER (decl) && !TREE_STATIC (decl)) diff --git a/gnu/gcc/gcc/expr.c b/gnu/gcc/gcc/expr.c index c6bc4263b86..8c5c80e1f66 100644 --- a/gnu/gcc/gcc/expr.c +++ b/gnu/gcc/gcc/expr.c @@ -1393,7 +1393,7 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall) static GTY(()) tree block_move_fn; void -init_block_move_fn (const char *asmspec) +init_block_move_fn (tree decl, const char *asmspec) { if (!block_move_fn) { @@ -1409,7 +1409,10 @@ init_block_move_fn (const char *asmspec) TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; TREE_NOTHROW (fn) = 1; - DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; + if (decl != NULL_TREE && DECL_VISIBILITY_SPECIFIED (decl)) + DECL_VISIBILITY (fn) = DECL_VISIBILITY (decl); + else + DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; DECL_VISIBILITY_SPECIFIED (fn) = 1; block_move_fn = fn; @@ -1425,7 +1428,7 @@ emit_block_move_libcall_fn (int for_call) static bool emitted_extern; if (!block_move_fn) - init_block_move_fn (NULL); + init_block_move_fn (NULL_TREE, NULL); if (for_call && !emitted_extern) { @@ -2597,7 +2600,7 @@ clear_storage_via_libcall (rtx object, rtx size, bool tailcall) static GTY(()) tree block_clear_fn; void -init_block_clear_fn (const char *asmspec) +init_block_clear_fn (tree decl, const char *asmspec) { if (!block_clear_fn) { @@ -2613,7 +2616,10 @@ init_block_clear_fn (const char *asmspec) TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; TREE_NOTHROW (fn) = 1; - DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; + if (decl != NULL_TREE && DECL_VISIBILITY_SPECIFIED (decl)) + DECL_VISIBILITY (fn) = DECL_VISIBILITY (decl); + else + DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; DECL_VISIBILITY_SPECIFIED (fn) = 1; block_clear_fn = fn; @@ -2629,7 +2635,7 @@ clear_storage_libcall_fn (int for_call) static bool emitted_extern; if (!block_clear_fn) - init_block_clear_fn (NULL); + init_block_clear_fn (NULL_TREE, NULL); if (for_call && !emitted_extern) { diff --git a/gnu/gcc/gcc/expr.h b/gnu/gcc/gcc/expr.h index 42b98937a82..c4434850c93 100644 --- a/gnu/gcc/gcc/expr.h +++ b/gnu/gcc/gcc/expr.h @@ -373,8 +373,9 @@ enum block_op_methods BLOCK_OP_TAILCALL }; -extern void init_block_move_fn (const char *); -extern void init_block_clear_fn (const char *); +extern void init_block_move_fn (tree, const char *); +extern void init_block_clear_fn (tree, const char *); +extern void init_stack_smash_fn (tree, const char *); extern rtx emit_block_move (rtx, rtx, rtx, enum block_op_methods); diff --git a/gnu/gcc/gcc/targhooks.c b/gnu/gcc/gcc/targhooks.c index 802df49b2cd..ce7bdbd9fa3 100644 --- a/gnu/gcc/gcc/targhooks.c +++ b/gnu/gcc/gcc/targhooks.c @@ -393,10 +393,49 @@ static GTY(()) int stack_protect_labelno; #include "c-common.h" +static GTY(()) tree stack_smash_fn; + +void +init_stack_smash_fn (tree decl, const char *asmspec) +{ + if (!stack_smash_fn) + { + tree args, fn; + + fn = get_identifier ("__stack_smash_handler"); + args = build_function_type_list (void_type_node, ptr_type_node, + NULL_TREE); + fn = build_decl (FUNCTION_DECL, fn, args); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + TREE_THIS_VOLATILE (fn) = 1; + TREE_NOTHROW (fn) = 1; + if (decl != NULL_TREE && DECL_VISIBILITY_SPECIFIED (decl)) + DECL_VISIBILITY (fn) = DECL_VISIBILITY (decl); + else + DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (fn) = 1; + stack_smash_fn = fn; + } + + if (asmspec) + set_user_assembler_name (stack_smash_fn, asmspec); +} + +static tree +emit_stack_smash_libcall_fn (void) +{ + if (!stack_smash_fn) + init_stack_smash_fn (NULL_TREE, NULL); + + return stack_smash_fn; +} + tree default_external_stack_protect_fail (void) { - tree t, func, type, init, stack_smash_handler; + tree t, func, type, init; const char *name = fname_as_string (0); size_t length = strlen (name); char name_buf[32]; @@ -420,26 +459,10 @@ default_external_stack_protect_fail (void) assemble_variable (func, 0, 0, 0); - /* Build a decl for __stack_smash_handler. */ - t = build_pointer_type (TREE_TYPE (func)); - t = build_function_type_list (void_type_node, t, NULL); - t = build_decl (FUNCTION_DECL, get_identifier ("__stack_smash_handler"), t); - TREE_STATIC (t) = 1; - TREE_PUBLIC (t) = 1; - DECL_EXTERNAL (t) = 1; - TREE_USED (t) = 1; - TREE_THIS_VOLATILE (t) = 1; - TREE_NOTHROW (t) = 1; - DECL_ARTIFICIAL (t) = 1; - DECL_IGNORED_P (t) = 1; - DECL_VISIBILITY (t) = VISIBILITY_DEFAULT; - DECL_VISIBILITY_SPECIFIED (t) = 1; - stack_smash_handler = t; - /* Generate a call to __stack_smash_handler(__func__). */ t = build_fold_addr_expr (func); t = tree_cons (NULL, t, NULL); - return build_function_call_expr (stack_smash_handler, t); + return build_function_call_expr (emit_stack_smash_libcall_fn (), t); } tree |