aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-11-28 09:18:59 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2013-11-28 09:18:59 +0100
commite361382f655dcba3b6538d9157c6d378db57158b (patch)
treeb8e14dee616a6f5428fd7b804709a5da8b7d3073 /gcc/cfgexpand.c
parent8b5e12023b56dfc83c037053612b08f5ee7eac61 (diff)
downloadgcc-e361382f655dcba3b6538d9157c6d378db57158b.zip
gcc-e361382f655dcba3b6538d9157c6d378db57158b.tar.gz
gcc-e361382f655dcba3b6538d9157c6d378db57158b.tar.bz2
cfgexpand.c (struct stack_vars_data): Add asan_base and asan_alignb fields.
* cfgexpand.c (struct stack_vars_data): Add asan_base and asan_alignb fields. (expand_stack_vars): For -fsanitize=address, use (and set initially) data->asan_base as base for vars and update asan_alignb. (expand_used_vars): Initialize data.asan_base and data.asan_alignb. Pass them to asan_emit_stack_protection. * asan.c (asan_detect_stack_use_after_return): New variable. (asan_emit_stack_protection): Add pbase and alignb arguments. Implement use after return sanitization. * asan.h (asan_emit_stack_protection): Adjust prototype. (ASAN_STACK_MAGIC_USE_AFTER_RET, ASAN_STACK_RETIRED_MAGIC): Define. From-SVN: r205476
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r--gcc/cfgexpand.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 207f876..622b7ea 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -890,6 +890,12 @@ struct stack_vars_data
/* Vector of partition representative decls in between the paddings. */
vec<tree> asan_decl_vec;
+
+ /* Base pseudo register for Address Sanitizer protected automatic vars. */
+ rtx asan_base;
+
+ /* Alignment needed for the Address Sanitizer protected automatic vars. */
+ unsigned int asan_alignb;
};
/* A subroutine of expand_used_vars. Give each partition representative
@@ -974,6 +980,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
alignb = stack_vars[i].alignb;
if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
{
+ base = virtual_stack_vars_rtx;
if ((flag_sanitize & SANITIZE_ADDRESS) && pred)
{
HOST_WIDE_INT prev_offset = frame_offset;
@@ -1002,10 +1009,13 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
if (repr_decl == NULL_TREE)
repr_decl = stack_vars[i].decl;
data->asan_decl_vec.safe_push (repr_decl);
+ data->asan_alignb = MAX (data->asan_alignb, alignb);
+ if (data->asan_base == NULL)
+ data->asan_base = gen_reg_rtx (Pmode);
+ base = data->asan_base;
}
else
offset = alloc_stack_frame_space (stack_vars[i].size, alignb);
- base = virtual_stack_vars_rtx;
base_align = crtl->max_used_stack_slot_alignment;
}
else
@@ -1792,6 +1802,8 @@ expand_used_vars (void)
data.asan_vec = vNULL;
data.asan_decl_vec = vNULL;
+ data.asan_base = NULL_RTX;
+ data.asan_alignb = 0;
/* Reorder decls to be protected by iterating over the variables
array multiple times, and allocating out of each phase in turn. */
@@ -1816,16 +1828,25 @@ expand_used_vars (void)
if (!data.asan_vec.is_empty ())
{
HOST_WIDE_INT prev_offset = frame_offset;
- HOST_WIDE_INT offset
- = alloc_stack_frame_space (ASAN_RED_ZONE_SIZE,
- ASAN_RED_ZONE_SIZE);
+ HOST_WIDE_INT offset, sz, redzonesz;
+ redzonesz = ASAN_RED_ZONE_SIZE;
+ sz = data.asan_vec[0] - prev_offset;
+ if (data.asan_alignb > ASAN_RED_ZONE_SIZE
+ && data.asan_alignb <= 4096
+ && sz + ASAN_RED_ZONE_SIZE >= data.asan_alignb)
+ redzonesz = ((sz + ASAN_RED_ZONE_SIZE + data.asan_alignb - 1)
+ & ~(data.asan_alignb - HOST_WIDE_INT_1)) - sz;
+ offset
+ = alloc_stack_frame_space (redzonesz, ASAN_RED_ZONE_SIZE);
data.asan_vec.safe_push (prev_offset);
data.asan_vec.safe_push (offset);
var_end_seq
= asan_emit_stack_protection (virtual_stack_vars_rtx,
+ data.asan_base,
+ data.asan_alignb,
data.asan_vec.address (),
- data.asan_decl_vec. address (),
+ data.asan_decl_vec.address (),
data.asan_vec.length ());
}