aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-01-08 18:01:58 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2013-01-08 18:01:58 +0100
commitaeb7e7c176070bfbdb4817c1992237f2e3e2019d (patch)
tree48b3c9aa4647fa4a5704ac3a66e96527996459b5
parentb4208463a3f454e3b10e3a3a306ee7416897c301 (diff)
downloadgcc-aeb7e7c176070bfbdb4817c1992237f2e3e2019d.zip
gcc-aeb7e7c176070bfbdb4817c1992237f2e3e2019d.tar.gz
gcc-aeb7e7c176070bfbdb4817c1992237f2e3e2019d.tar.bz2
re PR fortran/55341 (address-sanitizer and Fortran)
PR fortran/55341 * asan.c (asan_clear_shadow): New function. (asan_emit_stack_protection): Use it. From-SVN: r195025
-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 0862196..59d97ed 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 9d33876..4f9927b 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 ();