summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-01-08 17:01:58 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-01-08 17:01:58 +0000
commitcc72d6e932e3cf059a3d02c5f86380b4b217782f (patch)
tree48b3c9aa4647fa4a5704ac3a66e96527996459b5
parent3de3342f56968f13b265d28d6a555c8d3b16fa94 (diff)
downloadgcc-cc72d6e932e3cf059a3d02c5f86380b4b217782f.tar.gz
PR fortran/55341
* asan.c (asan_clear_shadow): New function. (asan_emit_stack_protection): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@195025 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/asan.c45
2 files changed, 47 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0862196b2a4..59d97edee7b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-01-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/55341
+ * asan.c (asan_clear_shadow): New function.
+ (asan_emit_stack_protection): Use it.
+
2013-01-08 Tejas Belagod <tejas.belagod@arm.com>
* config/aarch64/aarch64-simd.md (aarch64_simd_vec_<su>mult_lo_<mode>,
diff --git a/gcc/asan.c b/gcc/asan.c
index 9d3387616de..4f9927b9ef4 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -270,6 +270,45 @@ asan_shadow_cst (unsigned char shadow_bytes[4])
return GEN_INT (trunc_int_for_mode (val, SImode));
}
+/* Clear shadow memory at SHADOW_MEM, LEN bytes. Can't call a library call here
+ though. */
+
+static void
+asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
+{
+ rtx insn, insns, top_label, end, addr, tmp, jump;
+
+ start_sequence ();
+ clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
+ insns = get_insns ();
+ end_sequence ();
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ if (CALL_P (insn))
+ break;
+ if (insn == NULL_RTX)
+ {
+ emit_insn (insns);
+ return;
+ }
+
+ gcc_assert ((len & 3) == 0);
+ top_label = gen_label_rtx ();
+ addr = force_reg (Pmode, XEXP (shadow_mem, 0));
+ shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
+ end = force_reg (Pmode, plus_constant (Pmode, addr, len));
+ emit_label (top_label);
+
+ emit_move_insn (shadow_mem, const0_rtx);
+ tmp = expand_simple_binop (Pmode, PLUS, addr, GEN_INT (4), addr,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != addr)
+ emit_move_insn (addr, tmp);
+ emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
+ jump = get_last_insn ();
+ gcc_assert (JUMP_P (jump));
+ add_reg_note (jump, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE * 80 / 100));
+}
+
/* Insert code to protect stack vars. The prologue sequence should be emitted
directly, epilogue sequence returned. BASE is the register holding the
stack base, against which OFFSETS array offsets are relative to, OFFSETS
@@ -404,8 +443,7 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
(last_offset - prev_offset)
>> ASAN_SHADOW_SHIFT);
prev_offset = last_offset;
- clear_storage (shadow_mem, GEN_INT (last_size >> ASAN_SHADOW_SHIFT),
- BLOCK_OP_NORMAL);
+ asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
last_offset = offset;
last_size = 0;
}
@@ -418,8 +456,7 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
shadow_mem = adjust_address (shadow_mem, VOIDmode,
(last_offset - prev_offset)
>> ASAN_SHADOW_SHIFT);
- clear_storage (shadow_mem, GEN_INT (last_size >> ASAN_SHADOW_SHIFT),
- BLOCK_OP_NORMAL);
+ asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
}
do_pending_stack_adjust ();