aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-12-10 12:14:36 +0000
committerJakub Jelinek <jakub@redhat.com>2012-12-10 12:14:36 +0000
commit3d1a5756aca18384ba57fbf1889a292d02f0de60 (patch)
tree3bd1c13134ce9fb42d46d64f6d4cfee4d5b21d3f
parent58772f5b90c3a053716113fc864853a6d1183f12 (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@194355 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/asan.c110
-rw-r--r--gcc/varasm.c19
3 files changed, 131 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 249004e7dfc..d02c124426d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/asan.c b/gcc/asan.c
index b8f36cb5851..6c8ef187189 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -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;
}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ee42afc8cbd..3c420c013d8 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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). */