From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22401 invoked by alias); 1 Nov 2012 19:53:40 -0000 Received: (qmail 22351 invoked by uid 22791); 1 Nov 2012 19:53:39 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,TW_SV X-Spam-Check-By: sourceware.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 01 Nov 2012 19:53:24 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TU0ov-0004b0-9D for gcc-patches@gcc.gnu.org; Thu, 01 Nov 2012 15:52:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:1609) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TU0ou-0004aB-Sk for gcc-patches@gcc.gnu.org; Thu, 01 Nov 2012 15:52:53 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qA1JqpnY028669 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 1 Nov 2012 15:52:51 -0400 Received: from localhost (ovpn-116-40.ams2.redhat.com [10.36.116.40]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id qA1JqnnG001149 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 1 Nov 2012 15:52:51 -0400 Received: by localhost (Postfix, from userid 1000) id EF8752C010C; Thu, 1 Nov 2012 20:52:47 +0100 (CET) From: dodji@redhat.com To: gcc-patches@gcc.gnu.org Cc: dnovillo@google.com, jakub@redhat.com, wmi@google.com, davidxl@google.com, konstantin.s.serebryany@gmail.com Subject: [PATCH 07/13] Implement protection of global variables Date: Thu, 01 Nov 2012 19:53:00 -0000 Message-Id: <1351799566-31447-8-git-send-email-dodji@redhat.com> In-Reply-To: <1351799566-31447-1-git-send-email-dodji@redhat.com> References: <1351799566-31447-1-git-send-email-dodji@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2012-11/txt/msg00093.txt.bz2 From: jakub This patch implements the protection of global variables. The basic idea is to insert a red zone between two global variables and install a constructor function that calls the asan runtime to do the populating of the relevant shadow memory regions at load time. So the patch lays out the global variables as to insert a red zone between them. The size of the red zones is so that each variable starts on a 32 bytes boundary. Then it installs a constructor function that, for each global variable, calls the runtime asan library function __asan_register_globals_with an instance of this type: struct __asan_global { /* Address of the beginning of the global variable. */ const void *__beg; /* Initial size of the global variable. */ uptr __size; /* Size of the global variable + size of the red zone. This size is 32 bytes aligned. */ uptr __size_with_redzone; /* Name of the global variable. */ const void *__name; /* This is always set to NULL for now. */ uptr __has_dynamic_init; } The patch also installs a destructor function that calls the runtime asan library function _asan_unregister_globals. * varasm.c: Include asan.h. (assemble_noswitch_variable): Grow size by asan_red_zone_size if decl is asan protected. (place_block_symbol): Likewise. (assemble_variable): If decl is asan protected, increase DECL_ALIGN if needed, and for decls emitted using assemble_variable_contents append padding zeros after it. * Makefile.in (varasm.o): Depend on asan.h. * asan.c: Include output.h. (asan_pp, asan_pp_initialized): New variables. (asan_pp_initialize, asan_pp_string): New functions. (asan_emit_stack_protection): Use asan_pp{,_initialized} instead of local pp{,_initialized} vars, use asan_pp_initialize and asan_pp_string helpers. (asan_needs_local_alias, asan_protect_global, asan_global_struct, asan_add_global): New functions. (asan_finish_file): Protect global vars that can be protected. * asan.h (asan_protect_global): New prototype. (asan_red_zone_size): New inline function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/asan@192541 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog.asan | 20 ++++ gcc/Makefile.in | 2 +- gcc/asan.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++------ gcc/asan.h | 11 ++ gcc/varasm.c | 22 ++++ 5 files changed, 319 insertions(+), 35 deletions(-) diff --git a/gcc/ChangeLog.asan b/gcc/ChangeLog.asan index 23454f3..971de42 100644 --- a/gcc/ChangeLog.asan +++ b/gcc/ChangeLog.asan @@ -1,5 +1,25 @@ 2012-10-17 Jakub Jelinek + * varasm.c: Include asan.h. + (assemble_noswitch_variable): Grow size by asan_red_zone_size + if decl is asan protected. + (place_block_symbol): Likewise. + (assemble_variable): If decl is asan protected, increase + DECL_ALIGN if needed, and for decls emitted using + assemble_variable_contents append padding zeros after it. + * Makefile.in (varasm.o): Depend on asan.h. + * asan.c: Include output.h. + (asan_pp, asan_pp_initialized): New variables. + (asan_pp_initialize, asan_pp_string): New functions. + (asan_emit_stack_protection): Use asan_pp{,_initialized} + instead of local pp{,_initialized} vars, use asan_pp_initialize + and asan_pp_string helpers. + (asan_needs_local_alias, asan_protect_global, + asan_global_struct, asan_add_global): New functions. + (asan_finish_file): Protect global vars that can be protected. + * asan.h (asan_protect_global): New prototype. + (asan_red_zone_size): New inline function. + * Makefile.in (asan.o): Depend on $(EXPR_H) $(OPTABS_H). (cfgexpand.o): Depend on asan.h. * asan.c: Include expr.h and optabs.h. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2743e24..c6a9825 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2721,7 +2721,7 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ output.h $(DIAGNOSTIC_CORE_H) xcoffout.h debug.h $(GGC_H) $(TM_P_H) \ $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h $(BASIC_BLOCK_H) \ $(CGRAPH_H) $(TARGET_DEF_H) tree-mudflap.h \ - pointer-set.h $(COMMON_TARGET_H) + pointer-set.h $(COMMON_TARGET_H) asan.h function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \ $(TREE_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \ $(OPTABS_H) $(LIBFUNCS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \ diff --git a/gcc/asan.c b/gcc/asan.c index fe0e9a8..c435d35 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "expr.h" #include "optabs.h" +#include "output.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs @@ -87,6 +88,34 @@ alias_set_type asan_shadow_set = -1; alias set is used for all shadow memory accesses. */ static GTY(()) tree shadow_ptr_types[2]; +/* Asan pretty-printer, used for buidling of the description STRING_CSTs. */ +static pretty_printer asan_pp; +static bool asan_pp_initialized; + +/* Initialize asan_pp. */ + +static void +asan_pp_initialize (void) +{ + pp_construct (&asan_pp, /* prefix */NULL, /* line-width */0); + asan_pp_initialized = true; +} + +/* Create ADDR_EXPR of STRING_CST with asan_pp text. */ + +static tree +asan_pp_string (void) +{ + const char *buf = pp_base_formatted_text (&asan_pp); + size_t len = strlen (buf); + tree ret = build_string (len + 1, buf); + TREE_TYPE (ret) + = build_array_type (char_type_node, build_index_type (size_int (len))); + TREE_READONLY (ret) = 1; + TREE_STATIC (ret) = 1; + return build1 (ADDR_EXPR, build_pointer_type (char_type_node), ret); +} + /* Return a CONST_INT representing 4 subsequent shadow memory bytes. */ static rtx @@ -121,51 +150,38 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, HOST_WIDE_INT last_offset, last_size; int l; unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT; - static pretty_printer pp; - static bool pp_initialized; - const char *buf; - size_t len; tree str_cst; /* First of all, prepare the description string. */ - if (!pp_initialized) - { - pp_construct (&pp, /* prefix */NULL, /* line-width */0); - pp_initialized = true; - } - pp_clear_output_area (&pp); + if (!asan_pp_initialized) + asan_pp_initialize (); + + pp_clear_output_area (&asan_pp); if (DECL_NAME (current_function_decl)) - pp_base_tree_identifier (&pp, DECL_NAME (current_function_decl)); + pp_base_tree_identifier (&asan_pp, DECL_NAME (current_function_decl)); else - pp_string (&pp, ""); - pp_space (&pp); - pp_decimal_int (&pp, length / 2 - 1); - pp_space (&pp); + pp_string (&asan_pp, ""); + pp_space (&asan_pp); + pp_decimal_int (&asan_pp, length / 2 - 1); + pp_space (&asan_pp); for (l = length - 2; l; l -= 2) { tree decl = decls[l / 2 - 1]; - pp_wide_integer (&pp, offsets[l] - base_offset); - pp_space (&pp); - pp_wide_integer (&pp, offsets[l - 1] - offsets[l]); - pp_space (&pp); + pp_wide_integer (&asan_pp, offsets[l] - base_offset); + pp_space (&asan_pp); + pp_wide_integer (&asan_pp, offsets[l - 1] - offsets[l]); + pp_space (&asan_pp); if (DECL_P (decl) && DECL_NAME (decl)) { - pp_decimal_int (&pp, IDENTIFIER_LENGTH (DECL_NAME (decl))); - pp_space (&pp); - pp_base_tree_identifier (&pp, DECL_NAME (decl)); + pp_decimal_int (&asan_pp, IDENTIFIER_LENGTH (DECL_NAME (decl))); + pp_space (&asan_pp); + pp_base_tree_identifier (&asan_pp, DECL_NAME (decl)); } else - pp_string (&pp, "9 "); - pp_space (&pp); + pp_string (&asan_pp, "9 "); + pp_space (&asan_pp); } - buf = pp_base_formatted_text (&pp); - len = strlen (buf); - str_cst = build_string (len + 1, buf); - TREE_TYPE (str_cst) - = build_array_type (char_type_node, build_index_type (size_int (len))); - TREE_READONLY (str_cst) = 1; - TREE_STATIC (str_cst) = 1; - str_cst = build1 (ADDR_EXPR, build_pointer_type (char_type_node), str_cst); + str_cst = asan_pp_string (); /* Emit the prologue sequence. */ base = expand_binop (Pmode, add_optab, base, GEN_INT (base_offset), @@ -270,6 +286,75 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, return ret; } +/* Return true if DECL, a global var, might be overridden and needs + therefore a local alias. */ + +static bool +asan_needs_local_alias (tree decl) +{ + return DECL_WEAK (decl) || !targetm.binds_local_p (decl); +} + +/* Return true if DECL is a VAR_DECL that should be protected + by Address Sanitizer, by appending a red zone with protected + shadow memory after it and aligning it to at least + ASAN_RED_ZONE_SIZE bytes. */ + +bool +asan_protect_global (tree decl) +{ + rtx rtl, symbol; + section *sect; + + if (TREE_CODE (decl) != VAR_DECL + /* TLS vars aren't statically protectable. */ + || DECL_THREAD_LOCAL_P (decl) + /* Externs will be protected elsewhere. */ + || DECL_EXTERNAL (decl) + || !TREE_ASM_WRITTEN (decl) + || !DECL_RTL_SET_P (decl) + /* Comdat vars pose an ABI problem, we can't know if + the var that is selected by the linker will have + padding or not. */ + || DECL_ONE_ONLY (decl) + /* Similarly for common vars. People can use -fno-common. */ + || DECL_COMMON (decl) + /* Don't protect if using user section, often vars placed + into user section from multiple TUs are then assumed + to be an array of such vars, putting padding in there + breaks this assumption. */ + || (DECL_SECTION_NAME (decl) != NULL_TREE + && !DECL_HAS_IMPLICIT_SECTION_NAME_P (decl)) + || DECL_SIZE (decl) == 0 + || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT + || !valid_constant_size_p (DECL_SIZE_UNIT (decl)) + || DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE) + return false; + + rtl = DECL_RTL (decl); + if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF) + return false; + symbol = XEXP (rtl, 0); + + if (CONSTANT_POOL_ADDRESS_P (symbol) + || TREE_CONSTANT_POOL_ADDRESS_P (symbol)) + return false; + + sect = get_variable_section (decl, false); + if (sect->common.flags & SECTION_COMMON) + return false; + + if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) + return false; + +#ifndef ASM_OUTPUT_DEF + if (asan_needs_local_alias (decl)) + return false; +#endif + + return true; +} + /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. IS_STORE is either 1 (for a store) or 0 (for a load). SIZE_IN_BYTES is one of 1, 2, 4, 8, 16. */ @@ -568,6 +653,101 @@ transform_statements (void) } } +/* Build + struct __asan_global + { + const void *__beg; + uptr __size; + uptr __size_with_redzone; + const void *__name; + uptr __has_dynamic_init; + } type. */ + +static tree +asan_global_struct (void) +{ + static const char *field_names[5] + = { "__beg", "__size", "__size_with_redzone", + "__name", "__has_dynamic_init" }; + tree fields[5], ret; + int i; + + ret = make_node (RECORD_TYPE); + for (i = 0; i < 5; i++) + { + fields[i] + = build_decl (UNKNOWN_LOCATION, FIELD_DECL, + get_identifier (field_names[i]), + (i == 0 || i == 3) ? const_ptr_type_node + : build_nonstandard_integer_type (POINTER_SIZE, 1)); + DECL_CONTEXT (fields[i]) = ret; + if (i) + DECL_CHAIN (fields[i - 1]) = fields[i]; + } + TYPE_FIELDS (ret) = fields[0]; + TYPE_NAME (ret) = get_identifier ("__asan_global"); + layout_type (ret); + return ret; +} + +/* Append description of a single global DECL into vector V. + TYPE is __asan_global struct type as returned by asan_global_struct. */ + +static void +asan_add_global (tree decl, tree type, VEC(constructor_elt, gc) *v) +{ + tree init, uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type))); + unsigned HOST_WIDE_INT size; + tree str_cst, refdecl = decl; + VEC(constructor_elt, gc) *vinner = NULL; + + if (!asan_pp_initialized) + asan_pp_initialize (); + + pp_clear_output_area (&asan_pp); + if (DECL_NAME (decl)) + pp_base_tree_identifier (&asan_pp, DECL_NAME (decl)); + else + pp_string (&asan_pp, ""); + pp_space (&asan_pp); + pp_left_paren (&asan_pp); + pp_string (&asan_pp, main_input_filename); + pp_right_paren (&asan_pp); + str_cst = asan_pp_string (); + + if (asan_needs_local_alias (decl)) + { + char buf[20]; + ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", + VEC_length (constructor_elt, v) + 1); + refdecl = build_decl (DECL_SOURCE_LOCATION (decl), + VAR_DECL, get_identifier (buf), TREE_TYPE (decl)); + TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl); + TREE_READONLY (refdecl) = TREE_READONLY (decl); + TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl); + DECL_GIMPLE_REG_P (refdecl) = DECL_GIMPLE_REG_P (decl); + DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl); + DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl); + TREE_STATIC (refdecl) = 1; + TREE_PUBLIC (refdecl) = 0; + TREE_USED (refdecl) = 1; + assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl)); + } + + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, + fold_convert (const_ptr_type_node, + build_fold_addr_expr (refdecl))); + size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size)); + size += asan_red_zone_size (size); + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size)); + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, + fold_convert (const_ptr_type_node, str_cst)); + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, 0)); + init = build_constructor (type, vinner); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); +} + /* Module-level instrumentation. - Insert __asan_init() into the list of CTORs. - TODO: insert redzones around globals. @@ -577,10 +757,61 @@ void asan_finish_file (void) { tree ctor_statements = NULL_TREE; + struct varpool_node *vnode; + unsigned HOST_WIDE_INT gcount = 0; + append_to_statement_list (build_call_expr (asan_init_func (), 0), - &ctor_statements); + &ctor_statements); + FOR_EACH_DEFINED_VARIABLE (vnode) + if (asan_protect_global (vnode->symbol.decl)) + ++gcount; + if (gcount) + { + tree type = asan_global_struct (), var, ctor, decl; + tree uptr = build_nonstandard_integer_type (POINTER_SIZE, 1); + tree dtor_statements = NULL_TREE; + VEC(constructor_elt, gc) *v; + char buf[20]; + + type = build_array_type_nelts (type, gcount); + ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", 0); + var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf), + type); + TREE_STATIC (var) = 1; + TREE_PUBLIC (var) = 0; + DECL_ARTIFICIAL (var) = 1; + DECL_IGNORED_P (var) = 1; + v = VEC_alloc (constructor_elt, gc, gcount); + FOR_EACH_DEFINED_VARIABLE (vnode) + if (asan_protect_global (vnode->symbol.decl)) + asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v); + ctor = build_constructor (type, v); + TREE_CONSTANT (ctor) = 1; + TREE_STATIC (ctor) = 1; + DECL_INITIAL (var) = ctor; + varpool_assemble_decl (varpool_node (var)); + + type = build_function_type_list (void_type_node, + build_pointer_type (TREE_TYPE (type)), + uptr, NULL_TREE); + decl = build_fn_decl ("__asan_register_globals", type); + TREE_NOTHROW (decl) = 1; + append_to_statement_list (build_call_expr (decl, 2, + build_fold_addr_expr (var), + build_int_cst (uptr, gcount)), + &ctor_statements); + + decl = build_fn_decl ("__asan_unregister_globals", type); + TREE_NOTHROW (decl) = 1; + append_to_statement_list (build_call_expr (decl, 2, + build_fold_addr_expr (var), + build_int_cst (uptr, gcount)), + &dtor_statements); + cgraph_build_static_cdtor ('D', dtor_statements, + MAX_RESERVED_INIT_PRIORITY - 1); + } cgraph_build_static_cdtor ('I', ctor_statements, - MAX_RESERVED_INIT_PRIORITY - 1); + MAX_RESERVED_INIT_PRIORITY - 1); } /* Initialize shadow_ptr_types array. */ diff --git a/gcc/asan.h b/gcc/asan.h index 6f0edbf..d9368a8 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see extern void asan_finish_file (void); extern rtx asan_emit_stack_protection (rtx, HOST_WIDE_INT *, tree *, int); +extern bool asan_protect_global (tree); /* Alias set for accessing the shadow memory. */ extern alias_set_type asan_shadow_set; @@ -56,4 +57,14 @@ asan_protect_stack_decl (tree decl) return DECL_P (decl) && !DECL_ARTIFICIAL (decl); } +/* Return the size of padding needed to insert after a protected + decl of SIZE. */ + +static inline unsigned int +asan_red_zone_size (unsigned int size) +{ + unsigned int c = size & (ASAN_RED_ZONE_SIZE - 1); + return c ? 2 * ASAN_RED_ZONE_SIZE - c : ASAN_RED_ZONE_SIZE; +} + #endif /* TREE_ASAN */ diff --git a/gcc/varasm.c b/gcc/varasm.c index b300348..8a533ed 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-mudflap.h" #include "cgraph.h" #include "pointer-set.h" +#include "asan.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data @@ -1831,6 +1832,9 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect) size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); rounded = size; + if (flag_asan && asan_protect_global (decl)) + size += asan_red_zone_size (size); + /* Don't allocate zero bytes of common, since that means "undefined external" in the linker. */ if (size == 0) @@ -1897,6 +1901,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, const char *name; rtx decl_rtl, symbol; section *sect; + bool asan_protected = false; /* This function is supposed to handle VARIABLES. Ensure we have one. */ gcc_assert (TREE_CODE (decl) == VAR_DECL); @@ -1984,6 +1989,15 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, /* Compute the alignment of this data. */ align_variable (decl, dont_output_data); + + if (flag_asan + && asan_protect_global (decl) + && DECL_ALIGN (decl) < ASAN_RED_ZONE_SIZE * BITS_PER_UNIT) + { + asan_protected = true; + DECL_ALIGN (decl) = ASAN_RED_ZONE_SIZE * BITS_PER_UNIT; + } + set_mem_align (decl_rtl, DECL_ALIGN (decl)); if (TREE_PUBLIC (decl)) @@ -2022,6 +2036,12 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, if (DECL_ALIGN (decl) > BITS_PER_UNIT) ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl))); assemble_variable_contents (decl, name, dont_output_data); + if (asan_protected) + { + unsigned HOST_WIDE_INT int size + = tree_low_cst (DECL_SIZE_UNIT (decl), 1); + assemble_zeros (asan_red_zone_size (size)); + } } } @@ -6926,6 +6946,8 @@ place_block_symbol (rtx symbol) decl = SYMBOL_REF_DECL (symbol); alignment = DECL_ALIGN (decl); size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); + if (flag_asan && asan_protect_global (decl)) + size += asan_red_zone_size (size); } /* Calculate the object's offset from the start of the block. */ -- 1.7.11.7