* asan.c (asan_init_shadow_ptr_types): Move earlier in the file.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Dec 2012 12:14:36 +0000 (12:14 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 10 Dec 2012 12:14:36 +0000 (12:14 +0000)
Call initialize_sanitizer_builtins at the end.
(asan_pp_string): Use TREE_TYPE (shadow_ptr_types[0])
as character type instead of char_type_node.
(asan_emit_stack_protection): Call asan_init_shadow_ptr_types
if shadow_ptr_types isn't initialized.
(asan_protect_global): Return true for STRING_CSTs except those
created by asan_pp_string.
(count_string_csts, add_string_csts): New functions.
(struct asan_add_string_csts_data): New type.
(asan_finish_file): Clear flag_asan at the beginning, restore at the
end.  Traverse constant_pool_htab () to look for protected
STRING_CSTs.  Don't call initialize_sanitizer_builtins,
instead call asan_init_shadow_ptr_types if shadow_ptr_types isn't
initialized yet.
(asan_instrument): Don't call initialize_sanitizer_builtins.
* varasm.c (output_constant_def_contents): If STRING_CST should be
asan protected, align it sufficiently and emit padding after it.
(categorize_decl_for_section): If flag_asan, don't put STRING_CSTs
that should be asan protected into mergeable sections.  For
-fmerge-all-constants, ignore it for -fmudflap or if decl is
asan protected.

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

gcc/ChangeLog
gcc/asan.c
gcc/varasm.c

index 249004e..d02c124 100644 (file)
@@ -1,3 +1,28 @@
+2012-12-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * asan.c (asan_init_shadow_ptr_types): Move earlier in the file.
+       Call initialize_sanitizer_builtins at the end.
+       (asan_pp_string): Use TREE_TYPE (shadow_ptr_types[0])
+       as character type instead of char_type_node.
+       (asan_emit_stack_protection): Call asan_init_shadow_ptr_types
+       if shadow_ptr_types isn't initialized.
+       (asan_protect_global): Return true for STRING_CSTs except those
+       created by asan_pp_string.
+       (count_string_csts, add_string_csts): New functions.
+       (struct asan_add_string_csts_data): New type.
+       (asan_finish_file): Clear flag_asan at the beginning, restore at the
+       end.  Traverse constant_pool_htab () to look for protected
+       STRING_CSTs.  Don't call initialize_sanitizer_builtins,
+       instead call asan_init_shadow_ptr_types if shadow_ptr_types isn't
+       initialized yet.
+       (asan_instrument): Don't call initialize_sanitizer_builtins.
+       * varasm.c (output_constant_def_contents): If STRING_CST should be
+       asan protected, align it sufficiently and emit padding after it.
+       (categorize_decl_for_section): If flag_asan, don't put STRING_CSTs
+       that should be asan protected into mergeable sections.  For
+       -fmerge-all-constants, ignore it for -fmudflap or if decl is
+       asan protected.
+
 2012-12-10  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/arm/neon.ml (opcode): Add Vrintn, Vrinta, Vrintp, Vrintm,
index b8f36cb..6c8ef18 100644 (file)
@@ -212,6 +212,21 @@ alias_set_type asan_shadow_set = -1;
    alias set is used for all shadow memory accesses.  */
 static GTY(()) tree shadow_ptr_types[2];
 
+/* Initialize shadow_ptr_types array.  */
+
+static void
+asan_init_shadow_ptr_types (void)
+{
+  asan_shadow_set = new_alias_set ();
+  shadow_ptr_types[0] = build_distinct_type_copy (signed_char_type_node);
+  TYPE_ALIAS_SET (shadow_ptr_types[0]) = asan_shadow_set;
+  shadow_ptr_types[0] = build_pointer_type (shadow_ptr_types[0]);
+  shadow_ptr_types[1] = build_distinct_type_copy (short_integer_type_node);
+  TYPE_ALIAS_SET (shadow_ptr_types[1]) = asan_shadow_set;
+  shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]);
+  initialize_sanitizer_builtins ();
+}
+
 /* Asan pretty-printer, used for buidling of the description STRING_CSTs.  */
 static pretty_printer asan_pp;
 static bool asan_pp_initialized;
@@ -234,10 +249,11 @@ asan_pp_string (void)
   size_t len = strlen (buf);
   tree ret = build_string (len + 1, buf);
   TREE_TYPE (ret)
-    = build_array_type (char_type_node, build_index_type (size_int (len)));
+    = build_array_type (TREE_TYPE (shadow_ptr_types[0]),
+                       build_index_type (size_int (len)));
   TREE_READONLY (ret) = 1;
   TREE_STATIC (ret) = 1;
-  return build1 (ADDR_EXPR, build_pointer_type (char_type_node), ret);
+  return build1 (ADDR_EXPR, shadow_ptr_types[0], ret);
 }
 
 /* Return a CONST_INT representing 4 subsequent shadow memory bytes.  */
@@ -276,6 +292,9 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
   unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
   tree str_cst;
 
+  if (shadow_ptr_types[0] == NULL_TREE)
+    asan_init_shadow_ptr_types ();
+
   /* First of all, prepare the description string.  */
   if (!asan_pp_initialized)
     asan_pp_initialize ();
@@ -430,6 +449,16 @@ asan_protect_global (tree decl)
   rtx rtl, symbol;
   section *sect;
 
+  if (TREE_CODE (decl) == STRING_CST)
+    {
+      /* Instrument all STRING_CSTs except those created
+        by asan_pp_string here.  */
+      if (shadow_ptr_types[0] != NULL_TREE
+         && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+         && TREE_TYPE (TREE_TYPE (decl)) == TREE_TYPE (shadow_ptr_types[0]))
+       return false;
+      return true;
+    }
   if (TREE_CODE (decl) != VAR_DECL
       /* TLS vars aren't statically protectable.  */
       || DECL_THREAD_LOCAL_P (decl)
@@ -1580,6 +1609,50 @@ initialize_sanitizer_builtins (void)
 #undef DEF_SANITIZER_BUILTIN
 }
 
+/* Called via htab_traverse.  Count number of emitted
+   STRING_CSTs in the constant hash table.  */
+
+static int
+count_string_csts (void **slot, void *data)
+{
+  struct constant_descriptor_tree *desc
+    = (struct constant_descriptor_tree *) *slot;
+  if (TREE_CODE (desc->value) == STRING_CST
+      && TREE_ASM_WRITTEN (desc->value)
+      && asan_protect_global (desc->value))
+    ++*((unsigned HOST_WIDE_INT *) data);
+  return 1;
+}
+
+/* Helper structure to pass two parameters to
+   add_string_csts.  */
+
+struct asan_add_string_csts_data
+{
+  tree type;
+  vec<constructor_elt, va_gc> *v;
+};
+
+/* Called via htab_traverse.  Call asan_add_global
+   on emitted STRING_CSTs from the constant hash table.  */
+
+static int
+add_string_csts (void **slot, void *data)
+{
+  struct constant_descriptor_tree *desc
+    = (struct constant_descriptor_tree *) *slot;
+  if (TREE_CODE (desc->value) == STRING_CST
+      && TREE_ASM_WRITTEN (desc->value)
+      && asan_protect_global (desc->value))
+    {
+      struct asan_add_string_csts_data *aascd
+       = (struct asan_add_string_csts_data *) data;
+      asan_add_global (SYMBOL_REF_DECL (XEXP (desc->rtl, 0)),
+                      aascd->type, aascd->v);
+    }
+  return 1;
+}
+
 /* Needs to be GTY(()), because cgraph_build_static_cdtor may
    invoke ggc_collect.  */
 static GTY(()) tree asan_ctor_statements;
@@ -1595,13 +1668,20 @@ asan_finish_file (void)
   struct varpool_node *vnode;
   unsigned HOST_WIDE_INT gcount = 0;
 
-  initialize_sanitizer_builtins ();
+  if (shadow_ptr_types[0] == NULL_TREE)
+    asan_init_shadow_ptr_types ();
+  /* Avoid instrumenting code in the asan ctors/dtors.
+     We don't need to insert padding after the description strings,
+     nor after .LASAN* array.  */
+  flag_asan = 0;
 
   tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
   append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
   FOR_EACH_DEFINED_VARIABLE (vnode)
     if (asan_protect_global (vnode->symbol.decl))
       ++gcount;
+  htab_t const_desc_htab = constant_pool_htab ();
+  htab_traverse (const_desc_htab, count_string_csts, &gcount);
   if (gcount)
     {
       tree type = asan_global_struct (), var, ctor;
@@ -1622,6 +1702,10 @@ asan_finish_file (void)
       FOR_EACH_DEFINED_VARIABLE (vnode)
        if (asan_protect_global (vnode->symbol.decl))
          asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v);
+      struct asan_add_string_csts_data aascd;
+      aascd.type = TREE_TYPE (type);
+      aascd.v = v;
+      htab_traverse (const_desc_htab, add_string_csts, &aascd);
       ctor = build_constructor (type, v);
       TREE_CONSTANT (ctor) = 1;
       TREE_STATIC (ctor) = 1;
@@ -1644,20 +1728,7 @@ asan_finish_file (void)
     }
   cgraph_build_static_cdtor ('I', asan_ctor_statements,
                             MAX_RESERVED_INIT_PRIORITY - 1);
-}
-
-/* Initialize shadow_ptr_types array.  */
-
-static void
-asan_init_shadow_ptr_types (void)
-{
-  asan_shadow_set = new_alias_set ();
-  shadow_ptr_types[0] = build_distinct_type_copy (signed_char_type_node);
-  TYPE_ALIAS_SET (shadow_ptr_types[0]) = asan_shadow_set;
-  shadow_ptr_types[0] = build_pointer_type (shadow_ptr_types[0]);
-  shadow_ptr_types[1] = build_distinct_type_copy (short_integer_type_node);
-  TYPE_ALIAS_SET (shadow_ptr_types[1]) = asan_shadow_set;
-  shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]);
+  flag_asan = 1;
 }
 
 /* Instrument the current function.  */
@@ -1666,10 +1737,7 @@ static unsigned int
 asan_instrument (void)
 {
   if (shadow_ptr_types[0] == NULL_TREE)
-    {
-      asan_init_shadow_ptr_types ();
-      initialize_sanitizer_builtins ();
-    }
+    asan_init_shadow_ptr_types ();
   transform_statements ();
   return 0;
 }
index ee42afc..3c420c0 100644 (file)
@@ -3249,11 +3249,23 @@ output_constant_def_contents (rtx symbol)
     place_block_symbol (symbol);
   else
     {
+      bool asan_protected = false;
       align = DECL_ALIGN (decl);
       switch_to_section (get_constant_section (exp, align));
+      if (flag_asan && TREE_CODE (exp) == STRING_CST
+         && asan_protect_global (exp))
+       {
+         asan_protected = true;
+         align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
+       }
       if (align > BITS_PER_UNIT)
        ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
       assemble_constant_contents (exp, XSTR (symbol, 0), align);
+      if (asan_protected)
+       {
+         HOST_WIDE_INT size = get_constant_size (exp);
+         assemble_zeros (asan_red_zone_size (size));
+       }
     }
   if (flag_mudflap)
     mudflap_enqueue_constant (exp);
@@ -6157,7 +6169,9 @@ categorize_decl_for_section (const_tree decl, int reloc)
     return SECCAT_TEXT;
   else if (TREE_CODE (decl) == STRING_CST)
     {
-      if (flag_mudflap) /* or !flag_merge_constants */
+      if (flag_mudflap
+         || (flag_asan && asan_protect_global (CONST_CAST_TREE (decl))))
+      /* or !flag_merge_constants */
         return SECCAT_RODATA;
       else
        return SECCAT_RODATA_MERGE_STR;
@@ -6181,7 +6195,8 @@ categorize_decl_for_section (const_tree decl, int reloc)
        }
       else if (reloc & targetm.asm_out.reloc_rw_mask ())
        ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
-      else if (reloc || flag_merge_constants < 2)
+      else if (reloc || flag_merge_constants < 2 || flag_mudflap
+              || (flag_asan && asan_protect_global (CONST_CAST_TREE (decl))))
        /* C and C++ don't allow different variables to share the same
           location.  -fmerge-all-constants allows even that (at the
           expense of not conforming).  */