Add support for ASan odr_indicator.
authorMaxim Ostapenko <m.ostapenko@samsung.com>
Fri, 2 Dec 2016 07:39:27 +0000 (07:39 +0000)
committerMaxim Ostapenko <chefmax@gcc.gnu.org>
Fri, 2 Dec 2016 07:39:27 +0000 (09:39 +0200)
config/

        * bootstrap-asan.mk: Replace LSAN_OPTIONS=detect_leaks=0 with
        ASAN_OPTIONS=detect_leaks=0:use_odr_indicator=1.

gcc/

        * asan.c (asan_global_struct): Refactor.
        (create_odr_indicator): New function.
        (asan_needs_odr_indicator_p): Likewise.
        (is_odr_indicator): Likewise.
        (asan_add_global): Introduce odr_indicator_ptr. Pass it into global's
        constructor.
        (asan_protect_global): Do not protect odr indicators.

gcc/c-family/

* c-attribs.c (asan odr indicator): New attribute.
(handle_asan_odr_indicator_attribute): New function.

gcc/testsuite/

        * c-c++-common/asan/no-redundant-odr-indicators-1.c: New test.

From-SVN: r243153

config/ChangeLog
config/bootstrap-asan.mk
gcc/ChangeLog
gcc/asan.c
gcc/c-family/ChangeLog
gcc/c-family/c-attribs.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/asan/no-redundant-odr-indicators-1.c [new file with mode: 0644]

index 8dcb4831b17cfa877f4bdffc3f4d32880203926b..a823d21626bb51edc8e2878497bdcbcab7cfa80a 100644 (file)
@@ -1,3 +1,8 @@
+2016-12-02  Maxim Ostapenko  <m.ostapenko@samsung.com>
+
+       * bootstrap-asan.mk: Replace LSAN_OPTIONS=detect_leaks=0 with
+       ASAN_OPTIONS=detect_leaks=0:use_odr_indicator=1.
+
 2016-12-01  Matthias Klose  <doko@ubuntu.com>
 
        * pkg.m4: Remove.
index 70baaf9bb17354ae26919e2f2ff4006bbc656b45..e73d4c2cfb8078f0f65cf4b4b529b51c27442b07 100644 (file)
@@ -1,7 +1,7 @@
 # This option enables -fsanitize=address for stage2 and stage3.
 
 # Suppress LeakSanitizer in bootstrap.
-export LSAN_OPTIONS="detect_leaks=0"
+export ASAN_OPTIONS=detect_leaks=0:use_odr_indicator=1
 
 STAGE2_CFLAGS += -fsanitize=address
 STAGE3_CFLAGS += -fsanitize=address
index 75881ee7ace3b66fa1cbcbc5e8d0d8bc713a5821..ef080c77ed39ff54c31cebbdb4fdf9540e28664d 100644 (file)
@@ -1,3 +1,13 @@
+2016-12-02  Maxim Ostapenko  <m.ostapenko@samsung.com>
+
+       * asan.c (asan_global_struct): Refactor.
+       (create_odr_indicator): New function.
+       (asan_needs_odr_indicator_p): Likewise.
+       (is_odr_indicator): Likewise.
+       (asan_add_global): Introduce odr_indicator_ptr. Pass it into global's
+       constructor.
+       (asan_protect_global): Do not protect odr indicators.
+
 2016-12-01  Jeff Law  <law@redhat.com>
 
        * tree-ssa-threadedge.c
index cb5d6158e598f2452a1bbae85db1adc1b7542880..5af95472db9cafc08321fe805f4912f47d0b078a 100644 (file)
@@ -1388,6 +1388,16 @@ asan_needs_local_alias (tree decl)
   return DECL_WEAK (decl) || !targetm.binds_local_p (decl);
 }
 
+/* Return true if DECL, a global var, is an artificial ODR indicator symbol
+   therefore doesn't need protection.  */
+
+static bool
+is_odr_indicator (tree decl)
+{
+  return (DECL_ARTIFICIAL (decl)
+         && lookup_attribute ("asan odr indicator", DECL_ATTRIBUTES (decl)));
+}
+
 /* Return true if DECL is a VAR_DECL that should be protected
    by Address Sanitizer, by appending a red zone with protected
    shadow memory after it and aligning it to at least
@@ -1436,7 +1446,8 @@ asan_protect_global (tree decl)
       || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
       || !valid_constant_size_p (DECL_SIZE_UNIT (decl))
       || DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE
-      || TREE_TYPE (decl) == ubsan_get_source_location_type ())
+      || TREE_TYPE (decl) == ubsan_get_source_location_type ()
+      || is_odr_indicator (decl))
     return false;
 
   rtl = DECL_RTL (decl);
@@ -2266,14 +2277,15 @@ asan_dynamic_init_call (bool after_p)
 static tree
 asan_global_struct (void)
 {
-  static const char *field_names[8]
+  static const char *field_names[]
     = { "__beg", "__size", "__size_with_redzone",
-       "__name", "__module_name", "__has_dynamic_init", "__location", "__odr_indicator"};
-  tree fields[8], ret;
-  int i;
+       "__name", "__module_name", "__has_dynamic_init", "__location",
+       "__odr_indicator" };
+  tree fields[ARRAY_SIZE (field_names)], ret;
+  unsigned i;
 
   ret = make_node (RECORD_TYPE);
-  for (i = 0; i < 8; i++)
+  for (i = 0; i < ARRAY_SIZE (field_names); i++)
     {
       fields[i]
        = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
@@ -2295,6 +2307,63 @@ asan_global_struct (void)
   return ret;
 }
 
+/* Create and return odr indicator symbol for DECL.
+   TYPE is __asan_global struct type as returned by asan_global_struct.  */
+
+static tree
+create_odr_indicator (tree decl, tree type)
+{
+  char *name;
+  tree uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
+  tree decl_name
+    = (HAS_DECL_ASSEMBLER_NAME_P (decl) ? DECL_ASSEMBLER_NAME (decl)
+                                       : DECL_NAME (decl));
+  /* DECL_NAME theoretically might be NULL.  Bail out with 0 in this case.  */
+  if (decl_name == NULL_TREE)
+    return build_int_cst (uptr, 0);
+  size_t len = strlen (IDENTIFIER_POINTER (decl_name)) + sizeof ("__odr_asan_");
+  name = XALLOCAVEC (char, len);
+  snprintf (name, len, "__odr_asan_%s", IDENTIFIER_POINTER (decl_name));
+#ifndef NO_DOT_IN_LABEL
+  name[sizeof ("__odr_asan") - 1] = '.';
+#elif !defined(NO_DOLLAR_IN_LABEL)
+  name[sizeof ("__odr_asan") - 1] = '$';
+#endif
+  tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (name),
+                        char_type_node);
+  TREE_ADDRESSABLE (var) = 1;
+  TREE_READONLY (var) = 0;
+  TREE_THIS_VOLATILE (var) = 1;
+  DECL_GIMPLE_REG_P (var) = 0;
+  DECL_ARTIFICIAL (var) = 1;
+  DECL_IGNORED_P (var) = 1;
+  TREE_STATIC (var) = 1;
+  TREE_PUBLIC (var) = 1;
+  DECL_VISIBILITY (var) = DECL_VISIBILITY (decl);
+  DECL_VISIBILITY_SPECIFIED (var) = DECL_VISIBILITY_SPECIFIED (decl);
+
+  TREE_USED (var) = 1;
+  tree ctor = build_constructor_va (TREE_TYPE (var), 1, NULL_TREE,
+                                   build_int_cst (unsigned_type_node, 0));
+  TREE_CONSTANT (ctor) = 1;
+  TREE_STATIC (ctor) = 1;
+  DECL_INITIAL (var) = ctor;
+  DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("asan odr indicator"),
+                                    NULL, DECL_ATTRIBUTES (var));
+  make_decl_rtl (var);
+  varpool_node::finalize_decl (var);
+  return fold_convert (uptr, build_fold_addr_expr (var));
+}
+
+/* Return true if DECL, a global var, might be overridden and needs
+   an additional odr indicator symbol.  */
+
+static bool
+asan_needs_odr_indicator_p (tree decl)
+{
+  return !DECL_ARTIFICIAL (decl) && !DECL_WEAK (decl) && TREE_PUBLIC (decl);
+}
+
 /* Append description of a single global DECL into vector V.
    TYPE is __asan_global struct type as returned by asan_global_struct.  */
 
@@ -2335,6 +2404,9 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
       assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl));
     }
 
+  tree odr_indicator_ptr
+    = (asan_needs_odr_indicator_p (decl) ? create_odr_indicator (decl, type)
+                                        : build_int_cst (uptr, 0));
   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
                          fold_convert (const_ptr_type_node,
                                        build_fold_addr_expr (refdecl)));
@@ -2382,8 +2454,7 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
   else
     locptr = build_int_cst (uptr, 0);
   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
-  /* TODO: support ODR indicators.  */
-  CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, 0));
+  CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, odr_indicator_ptr);
   init = build_constructor (type, vinner);
   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
 }
index 183493d6e3ac33f6d6a3879d7976ceffd1592b23..58907981b96986bb508d90a7260666aa76be4d65 100644 (file)
@@ -1,3 +1,8 @@
+2016-12-02  Maxim Ostapenko  <m.ostapenko@samsung.com>
+
+       * c-attribs.c (asan odr indicator): New attribute.
+       (handle_asan_odr_indicator_attribute): New function.
+
 2016-11-26  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
 
        * c-common.c (c_common_nodes_and_builtins): Remove initialization of
index 964efe94bb7261696abcde97e99c5db9c7906a0b..f5adadee3af02d83a7faa7a02b2d81b9cca3550a 100644 (file)
@@ -57,6 +57,8 @@ static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
                                                         int, bool *);
 static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
                                                    bool *);
+static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int,
+                                                bool *);
 static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
@@ -292,6 +294,9 @@ const struct attribute_spec c_common_attribute_table[] =
   { "no_sanitize_undefined",  0, 0, true, false, false,
                              handle_no_sanitize_undefined_attribute,
                              false },
+  { "asan odr indicator",     0, 0, true, false, false,
+                             handle_asan_odr_indicator_attribute,
+                             false },
   { "warning",               1, 1, true,  false, false,
                              handle_error_attribute, false },
   { "error",                 1, 1, true,  false, false,
@@ -591,6 +596,15 @@ handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
   return NULL_TREE;
 }
 
+/* Handle an "asan odr indicator" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *)
+{
+  return NULL_TREE;
+}
+
 /* Handle a "stack_protect" attribute; arguments as in
    struct attribute_spec.handler.  */
 
index dcbdf565208edba5a69d5ee631a7167d3252db64..c000e07cade92d003136ee3ee7785d25291c74dd 100644 (file)
@@ -1,3 +1,7 @@
+2016-12-02  Maxim Ostapenko  <m.ostapenko@samsung.com>
+
+       * c-c++-common/asan/no-redundant-odr-indicators-1.c: New test.
+
 2016-12-01  Elizebeth Punnoose  <elizebeth.punnoose@hpe.com>
 
        PR fortran/77505
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-odr-indicators-1.c b/gcc/testsuite/c-c++-common/asan/no-redundant-odr-indicators-1.c
new file mode 100644 (file)
index 0000000..9231264
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+/* Local variables should not have odr indicators.  */
+static int a = 2;
+/* Thread local variables should not have odr indicators.  */
+__thread int b = 3;
+/* Externally visible  variables should have odr indicators.  */
+int c = 1;
+
+int main () {
+    return 0;
+}
+
+/* { dg-final { scan-assembler-not "odr_asan\[\.\$\]a" } } */
+/* { dg-final { scan-assembler-not "odr_asan\[\.\$\]b" } } */
+/* { dg-final { scan-assembler "odr_asan\[\.\$\]c" } } */