]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR fortran/55341 (address-sanitizer and Fortran)
authorJakub Jelinek <jakub@redhat.com>
Tue, 8 Jan 2013 17:01:58 +0000 (18:01 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 8 Jan 2013 17:01:58 +0000 (18:01 +0100)
PR fortran/55341
* asan.c (asan_clear_shadow): New function.
(asan_emit_stack_protection): Use it.

From-SVN: r195025

gcc/ChangeLog
gcc/asan.c

index 0862196b2a4b491b71a4298edc6d16fcacfb21c0..59d97edee7b29fc6d2af5f8c00cd8dd5badbe928 100644 (file)
@@ -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>,
index 9d3387616de042901bcb015b7130ff93cdf90594..4f9927b9ef44aa7d9c7efc4355ba95d389b8a2b9 100644 (file)
@@ -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 ();