]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
asan.c (report_error_func): Add SLOW_P argument, use BUILT_IN_ASAN_*_N if set.
authorJakub Jelinek <jakub@redhat.com>
Fri, 30 May 2014 18:37:59 +0000 (20:37 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 30 May 2014 18:37:59 +0000 (20:37 +0200)
* asan.c (report_error_func): Add SLOW_P argument, use
BUILT_IN_ASAN_*_N if set.
(build_check_stmt): Likewise.
(instrument_derefs): If T has insufficient alignment,
force same handling as for odd sizes.

* c-c++-common/asan/misalign-1.c: New test.
* c-c++-common/asan/misalign-2.c: New test.

From-SVN: r211092

gcc/ChangeLog
gcc/asan.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/asan/misalign-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/asan/misalign-2.c [new file with mode: 0644]

index 3d20e13d14f0113ec61086321b71c32ec2dcf831..233f05fc7413c1052531fe1041899814ad0de746 100644 (file)
@@ -1,5 +1,11 @@
 2014-05-30  Jakub Jelinek  <jakub@redhat.com>
 
+       * asan.c (report_error_func): Add SLOW_P argument, use
+       BUILT_IN_ASAN_*_N if set.
+       (build_check_stmt): Likewise.
+       (instrument_derefs): If T has insufficient alignment,
+       force same handling as for odd sizes.
+
        * sanitizer.def (BUILT_IN_ASAN_REPORT_LOAD_N,
        BUILT_IN_ASAN_REPORT_STORE_N): New.
        * asan.c (struct asan_mem_ref): Change access_size type to
index beb002374a2a9f34c087e29eb1f94066ac1b9b45..339765523a8f79f312dafdb3c57768eb562f65f0 100644 (file)
@@ -1319,7 +1319,7 @@ asan_protect_global (tree decl)
    IS_STORE is either 1 (for a store) or 0 (for a load).  */
 
 static tree
-report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes)
+report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes, bool slow_p)
 {
   static enum built_in_function report[2][6]
     = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
@@ -1329,7 +1329,8 @@ report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes)
          BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
          BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
   if ((size_in_bytes & (size_in_bytes - 1)) != 0
-      || size_in_bytes > 16)
+      || size_in_bytes > 16
+      || slow_p)
     return builtin_decl_implicit (report[is_store][5]);
   return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
 }
@@ -1508,7 +1509,8 @@ build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
 
 static void
 build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
-                 bool before_p, bool is_store, HOST_WIDE_INT size_in_bytes)
+                 bool before_p, bool is_store, HOST_WIDE_INT size_in_bytes,
+                 bool slow_p = false)
 {
   gimple_stmt_iterator gsi;
   basic_block then_bb, else_bb;
@@ -1522,9 +1524,15 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
   HOST_WIDE_INT real_size_in_bytes = size_in_bytes;
   tree sz_arg = NULL_TREE;
 
-  if ((size_in_bytes & (size_in_bytes - 1)) != 0
-      || size_in_bytes > 16)
-    real_size_in_bytes = 1;
+  if (size_in_bytes == 1)
+    slow_p = false;
+  else if ((size_in_bytes & (size_in_bytes - 1)) != 0
+          || size_in_bytes > 16
+          || slow_p)
+    {
+      real_size_in_bytes = 1;
+      slow_p = true;
+    }
 
   /* Get an iterator on the point where we can add the condition
      statement for the instrumentation.  */
@@ -1582,8 +1590,8 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
       t = gimple_assign_lhs (gimple_seq_last (seq));
       gimple_seq_set_location (seq, location);
       gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
-      /* For weird access sizes, check first and last byte.  */
-      if (real_size_in_bytes != size_in_bytes)
+      /* For weird access sizes or misaligned, check first and last byte.  */
+      if (slow_p)
        {
          g = gimple_build_assign_with_ops (PLUS_EXPR,
                                            make_ssa_name (uintptr_type, NULL),
@@ -1626,7 +1634,7 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
 
   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
   gsi = gsi_start_bb (then_bb);
-  g = gimple_build_call (report_error_func (is_store, size_in_bytes),
+  g = gimple_build_call (report_error_func (is_store, size_in_bytes, slow_p),
                         sz_arg ? 2 : 1, base_addr, sz_arg);
   gimple_set_location (g, location);
   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
@@ -1722,8 +1730,31 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
   base = build_fold_addr_expr (t);
   if (!has_mem_ref_been_instrumented (base, size_in_bytes))
     {
+      bool slow_p = false;
+      if (size_in_bytes > 1)
+       {
+         if ((size_in_bytes & (size_in_bytes - 1)) != 0
+             || size_in_bytes > 16)
+           slow_p = true;
+         else
+           {
+             unsigned int align = get_object_alignment (t);
+             if (align < size_in_bytes * BITS_PER_UNIT)
+               {
+                 /* On non-strict alignment targets, if
+                    16-byte access is just 8-byte aligned,
+                    this will result in misaligned shadow
+                    memory 2 byte load, but otherwise can
+                    be handled using one read.  */
+                 if (size_in_bytes != 16
+                     || STRICT_ALIGNMENT
+                     || align < 8 * BITS_PER_UNIT)
+                   slow_p = true;
+               }
+           }
+       }
       build_check_stmt (location, base, iter, /*before_p=*/true,
-                       is_store, size_in_bytes);
+                       is_store, size_in_bytes, slow_p);
       update_mem_ref_hash_table (base, size_in_bytes);
       update_mem_ref_hash_table (t, size_in_bytes);
     }
index 8beaf53879cce94ddba0a9dce1feac1cc17fa3f4..89cb55c1b00c18b5567bcf400cf81e7d16f6bae1 100644 (file)
@@ -1,5 +1,8 @@
 2014-05-30  Jakub Jelinek  <jakub@redhat.com>
 
+       * c-c++-common/asan/misalign-1.c: New test.
+       * c-c++-common/asan/misalign-2.c: New test.
+
        * g++.dg/asan/asan_test.C: Add -std=c++11 and
        -DSANITIZER_USE_DEJAGNU_GTEST=1 to dg-options, remove
        -DASAN_USE_DEJAGNU_GTEST=1.
diff --git a/gcc/testsuite/c-c++-common/asan/misalign-1.c b/gcc/testsuite/c-c++-common/asan/misalign-1.c
new file mode 100644 (file)
index 0000000..0c5b6e0
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do run { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2" } */
+/* { dg-shouldfail "asan" } */
+
+struct S { int i; } __attribute__ ((packed));
+
+__attribute__((noinline, noclone)) int
+foo (struct S *s)
+{
+  return s->i;
+}
+
+__attribute__((noinline, noclone)) int
+bar (int *s)
+{
+  return *s;
+}
+
+__attribute__((noinline, noclone)) struct S
+baz (struct S *s)
+{
+  return *s;
+}
+
+int
+main ()
+{
+  struct T { char a[3]; struct S b[3]; char c; } t;
+  int v = 5;
+  struct S *p = t.b;
+  asm volatile ("" : "+rm" (p));
+  p += 3;
+  if (bar (&v) != 5) __builtin_abort ();
+  volatile int w = foo (p);
+  return 0;
+}
+
+/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*foo(\[^\n\r]*misalign-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/asan/misalign-2.c b/gcc/testsuite/c-c++-common/asan/misalign-2.c
new file mode 100644 (file)
index 0000000..7fbe299
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do run { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2" } */
+/* { dg-shouldfail "asan" } */
+
+struct S { int i; } __attribute__ ((packed));
+
+__attribute__((noinline, noclone)) int
+foo (struct S *s)
+{
+  return s->i;
+}
+
+__attribute__((noinline, noclone)) int
+bar (int *s)
+{
+  return *s;
+}
+
+__attribute__((noinline, noclone)) struct S
+baz (struct S *s)
+{
+  return *s;
+}
+
+int
+main ()
+{
+  struct T { char a[3]; struct S b[3]; char c; } t;
+  int v = 5;
+  struct S *p = t.b;
+  asm volatile ("" : "+rm" (p));
+  p += 3;
+  if (bar (&v) != 5) __builtin_abort ();
+  volatile struct S w = baz (p);
+  return 0;
+}
+
+/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ (in _*baz(\[^\n\r]*misalign-2.c:22|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "    #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */