Make stack epilogue more efficient 78/210378/3
authormarxin <marxin@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 3 Jul 2017 09:26:31 +0000 (09:26 +0000)
committerDongkyun Son <dongkyun.s@samsung.com>
Mon, 22 Jul 2019 11:51:58 +0000 (20:51 +0900)
2017-07-03  Martin Liska  <mliska@suse.cz>

* asan.c (asan_emit_stack_protection): Unpoison just red zones
and shadow memory of auto variables which are subject of
use-after-scope sanitization.
(asan_expand_mark_ifn): Add do set only when is_poison.

(cherry picked 355c17620ce)

Change-Id: Ib36a512acb3e0dcb9e7dbfbd9a55661694e7e749
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@249900 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/asan.c

index 10d69ee..c5a8c80 100644 (file)
@@ -1,3 +1,10 @@
+2017-07-03  Martin Liska  <mliska@suse.cz>
+
+       * asan.c (asan_emit_stack_protection): Unpoison just red zones
+       and shadow memory of auto variables which are subject of
+       use-after-scope sanitization.
+       (asan_expand_mark_ifn): Add do set only when is_poison.
+
 2018-01-01  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/83623
index 0f5419f..20eae75 100644 (file)
@@ -1071,7 +1071,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   HOST_WIDE_INT base_offset = offsets[length - 1];
   HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
   HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
-  HOST_WIDE_INT last_offset;
+  HOST_WIDE_INT last_offset, last_size;
   int l;
   unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
   tree str_cst, decl, id;
@@ -1306,58 +1306,55 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   if (STRICT_ALIGNMENT)
     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
 
-  /* Unpoison shadow memory of a stack at the very end of a function.
-     As we're poisoning stack variables at the end of their scope,
-     shadow memory must be properly unpoisoned here.  The easiest approach
-     would be to collect all variables that should not be unpoisoned and
-     we unpoison shadow memory of the whole stack except ranges
-     occupied by these variables.  */
+  prev_offset = base_offset;
   last_offset = base_offset;
-  HOST_WIDE_INT current_offset = last_offset;
-  if (length)
+  last_size = 0;
+  for (l = length; l; l -= 2)
     {
-      HOST_WIDE_INT var_end_offset = 0;
-      HOST_WIDE_INT stack_start = offsets[length - 1];
-      gcc_assert (last_offset == stack_start);
-
-      for (int l = length - 2; l > 0; l -= 2)
+      offset = base_offset + ((offsets[l - 1] - base_offset)
+                            & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
+      if (last_offset + last_size != offset)
        {
-         HOST_WIDE_INT var_offset = offsets[l];
-         current_offset = var_offset;
-         var_end_offset = offsets[l - 1];
-         HOST_WIDE_INT rounded_size = ROUND_UP (var_end_offset - var_offset,
-                                            BITS_PER_UNIT);
+         shadow_mem = adjust_address (shadow_mem, VOIDmode,
+                                      (last_offset - prev_offset)
+                                      >> ASAN_SHADOW_SHIFT);
+         prev_offset = last_offset;
+         asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
+         last_offset = offset;
+         last_size = 0;
+       }
+      last_size += base_offset + ((offsets[l - 2] - base_offset)
+                                 & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
+                  - offset;
 
-         /* Should we unpoison the variable?  */
+      /* Unpoison shadow memory that corresponds to a variable that is 
+        is subject of use-after-return sanitization.  */
+      if (l > 2)
+       {
+         decl = decls[l / 2 - 2];
          if (asan_handled_variables != NULL
              && asan_handled_variables->contains (decl))
            {
+             HOST_WIDE_INT size = offsets[l - 3] - offsets[l - 2];
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                  const char *n = (DECL_NAME (decl)
                                   ? IDENTIFIER_POINTER (DECL_NAME (decl))
                                   : "<unknown>");
                  fprintf (dump_file, "Unpoisoning shadow stack for variable: "
-                          "%s (%" PRId64 "B)\n", n,
-                          var_end_offset - var_offset);
+                          "%s (%" PRId64 " B)\n", n, size);
                }
 
-             unsigned HOST_WIDE_INT s
-               = shadow_mem_size (current_offset - last_offset);
-             asan_clear_shadow (shadow_mem, s);
-             HOST_WIDE_INT shift
-               = shadow_mem_size (current_offset - last_offset + rounded_size);
-             shadow_mem = adjust_address (shadow_mem, VOIDmode, shift);
-             last_offset = var_offset + rounded_size;
-             current_offset = last_offset;
+               last_size += size & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
            }
-
        }
-
-      /* Handle last redzone.  */
-      current_offset = offsets[0];
-      asan_clear_shadow (shadow_mem,
-                        shadow_mem_size (current_offset - last_offset));
+    }
+  if (last_size)
+    {
+      shadow_mem = adjust_address (shadow_mem, VOIDmode,
+                                  (last_offset - prev_offset)
+                                  >> ASAN_SHADOW_SHIFT);
+      asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
     }
 
   /* Clean-up set with instrumented stack variables.  */
@@ -2721,9 +2718,13 @@ asan_expand_mark_ifn (gimple_stmt_iterator *iter)
   gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
   tree decl = TREE_OPERAND (base, 0);
   gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
-  if (asan_handled_variables == NULL)
-    asan_handled_variables = new hash_set<tree> (16);
-  asan_handled_variables->add (decl);
+
+  if (is_poison)
+    {
+      if (asan_handled_variables == NULL)
+       asan_handled_variables = new hash_set<tree> (16);
+      asan_handled_variables->add (decl);
+    }
   tree len = gimple_call_arg (g, 2);
 
   gcc_assert (tree_fits_shwi_p (len));