Commit 94fce891 by Jakub Jelinek Committed by Jakub Jelinek

asan.c (asan_init_shadow_ptr_types): Move earlier in the file.

	* 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.

From-SVN: r194355
parent 8d28afb4
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> 2012-12-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/arm/neon.ml (opcode): Add Vrintn, Vrinta, Vrintp, Vrintm, * config/arm/neon.ml (opcode): Add Vrintn, Vrinta, Vrintp, Vrintm,
...@@ -212,6 +212,21 @@ alias_set_type asan_shadow_set = -1; ...@@ -212,6 +212,21 @@ alias_set_type asan_shadow_set = -1;
alias set is used for all shadow memory accesses. */ alias set is used for all shadow memory accesses. */
static GTY(()) tree shadow_ptr_types[2]; 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. */ /* Asan pretty-printer, used for buidling of the description STRING_CSTs. */
static pretty_printer asan_pp; static pretty_printer asan_pp;
static bool asan_pp_initialized; static bool asan_pp_initialized;
...@@ -234,10 +249,11 @@ asan_pp_string (void) ...@@ -234,10 +249,11 @@ asan_pp_string (void)
size_t len = strlen (buf); size_t len = strlen (buf);
tree ret = build_string (len + 1, buf); tree ret = build_string (len + 1, buf);
TREE_TYPE (ret) 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_READONLY (ret) = 1;
TREE_STATIC (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. */ /* 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, ...@@ -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; unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
tree str_cst; tree str_cst;
if (shadow_ptr_types[0] == NULL_TREE)
asan_init_shadow_ptr_types ();
/* First of all, prepare the description string. */ /* First of all, prepare the description string. */
if (!asan_pp_initialized) if (!asan_pp_initialized)
asan_pp_initialize (); asan_pp_initialize ();
...@@ -430,6 +449,16 @@ asan_protect_global (tree decl) ...@@ -430,6 +449,16 @@ asan_protect_global (tree decl)
rtx rtl, symbol; rtx rtl, symbol;
section *sect; 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 if (TREE_CODE (decl) != VAR_DECL
/* TLS vars aren't statically protectable. */ /* TLS vars aren't statically protectable. */
|| DECL_THREAD_LOCAL_P (decl) || DECL_THREAD_LOCAL_P (decl)
...@@ -1580,6 +1609,50 @@ initialize_sanitizer_builtins (void) ...@@ -1580,6 +1609,50 @@ initialize_sanitizer_builtins (void)
#undef DEF_SANITIZER_BUILTIN #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 /* Needs to be GTY(()), because cgraph_build_static_cdtor may
invoke ggc_collect. */ invoke ggc_collect. */
static GTY(()) tree asan_ctor_statements; static GTY(()) tree asan_ctor_statements;
...@@ -1595,13 +1668,20 @@ asan_finish_file (void) ...@@ -1595,13 +1668,20 @@ asan_finish_file (void)
struct varpool_node *vnode; struct varpool_node *vnode;
unsigned HOST_WIDE_INT gcount = 0; 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); tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
FOR_EACH_DEFINED_VARIABLE (vnode) FOR_EACH_DEFINED_VARIABLE (vnode)
if (asan_protect_global (vnode->symbol.decl)) if (asan_protect_global (vnode->symbol.decl))
++gcount; ++gcount;
htab_t const_desc_htab = constant_pool_htab ();
htab_traverse (const_desc_htab, count_string_csts, &gcount);
if (gcount) if (gcount)
{ {
tree type = asan_global_struct (), var, ctor; tree type = asan_global_struct (), var, ctor;
...@@ -1622,6 +1702,10 @@ asan_finish_file (void) ...@@ -1622,6 +1702,10 @@ asan_finish_file (void)
FOR_EACH_DEFINED_VARIABLE (vnode) FOR_EACH_DEFINED_VARIABLE (vnode)
if (asan_protect_global (vnode->symbol.decl)) if (asan_protect_global (vnode->symbol.decl))
asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v); 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); ctor = build_constructor (type, v);
TREE_CONSTANT (ctor) = 1; TREE_CONSTANT (ctor) = 1;
TREE_STATIC (ctor) = 1; TREE_STATIC (ctor) = 1;
...@@ -1644,20 +1728,7 @@ asan_finish_file (void) ...@@ -1644,20 +1728,7 @@ asan_finish_file (void)
} }
cgraph_build_static_cdtor ('I', asan_ctor_statements, cgraph_build_static_cdtor ('I', asan_ctor_statements,
MAX_RESERVED_INIT_PRIORITY - 1); MAX_RESERVED_INIT_PRIORITY - 1);
} flag_asan = 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]);
} }
/* Instrument the current function. */ /* Instrument the current function. */
...@@ -1666,10 +1737,7 @@ static unsigned int ...@@ -1666,10 +1737,7 @@ static unsigned int
asan_instrument (void) asan_instrument (void)
{ {
if (shadow_ptr_types[0] == NULL_TREE) if (shadow_ptr_types[0] == NULL_TREE)
{ asan_init_shadow_ptr_types ();
asan_init_shadow_ptr_types ();
initialize_sanitizer_builtins ();
}
transform_statements (); transform_statements ();
return 0; return 0;
} }
......
...@@ -3249,11 +3249,23 @@ output_constant_def_contents (rtx symbol) ...@@ -3249,11 +3249,23 @@ output_constant_def_contents (rtx symbol)
place_block_symbol (symbol); place_block_symbol (symbol);
else else
{ {
bool asan_protected = false;
align = DECL_ALIGN (decl); align = DECL_ALIGN (decl);
switch_to_section (get_constant_section (exp, align)); 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) if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
assemble_constant_contents (exp, XSTR (symbol, 0), align); 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) if (flag_mudflap)
mudflap_enqueue_constant (exp); mudflap_enqueue_constant (exp);
...@@ -6157,7 +6169,9 @@ categorize_decl_for_section (const_tree decl, int reloc) ...@@ -6157,7 +6169,9 @@ categorize_decl_for_section (const_tree decl, int reloc)
return SECCAT_TEXT; return SECCAT_TEXT;
else if (TREE_CODE (decl) == STRING_CST) 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; return SECCAT_RODATA;
else else
return SECCAT_RODATA_MERGE_STR; return SECCAT_RODATA_MERGE_STR;
...@@ -6181,7 +6195,8 @@ categorize_decl_for_section (const_tree decl, int reloc) ...@@ -6181,7 +6195,8 @@ categorize_decl_for_section (const_tree decl, int reloc)
} }
else if (reloc & targetm.asm_out.reloc_rw_mask ()) else if (reloc & targetm.asm_out.reloc_rw_mask ())
ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; 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 /* C and C++ don't allow different variables to share the same
location. -fmerge-all-constants allows even that (at the location. -fmerge-all-constants allows even that (at the
expense of not conforming). */ expense of not conforming). */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment