sanitizer.def: Add Address Sanitizer builtins.

* sanitizer.def: Add Address Sanitizer builtins.
	Rename BUILT_IN_TSAN_READ_* to BUILT_IN_TSAN_READ* and
	BUILT_IN_TSAN_WRITE_* to BUILT_IN_TSAN_WRITE*.
	* Makefile.in (asan.o): Depend on langhooks.h.
	(tsan.o): Depend on asan.h.
	* asan.h (initialize_sanitizer_builtins): New prototype.
	* asan.c: Include langhooks.h.
	(report_error_func): Use builtin_decl_implicit of corresponding
	BUILT_IN_ASAN_REPORT_{LOAD,STORE}*.
	(asan_init_func): Removed.
	(initialize_sanitizer_builtins): New function.
	(asan_finish_file): Call it.  Use builtin_decl_implicit
	on BUILT_IN_ASAN_{INIT,{,UN}REGISTER_GLOBALS}.
	(asan_instrument): Call initialize_sanitizer_builtins.
	* builtins.def (DEF_SANITIZER_BUILTIN): Change condition to
	(flag_asan || flag_tsan).
	* tsan.c: Include asan.h and tsan.h.
	(get_memory_access_decl): Rename BUILT_IN_TSAN_{READ,WRITE}_*
	to BUILT_IN_TSAN_{READ,WRITE}*.
	(tsan_pass): Call initialize_sanitizer_builtins.
	(tsan_gate, tsan_gate_O0): Don't check if
	builtin_decl_implicit_p (BUILT_IN_TSAN_INIT) is true.
	(tsan_finish_file): Call initialize_sanitizer_builtins.
	* builtin-types.def (BT_FN_VOID_PTR_PTRMODE): New fn type.

From-SVN: r194103
This commit is contained in:
Jakub Jelinek 2012-12-03 18:28:10 +01:00 committed by Jakub Jelinek
parent f41e5bd19d
commit 0e668eaf77
8 changed files with 174 additions and 75 deletions

View File

@ -1,3 +1,30 @@
2012-12-03 Jakub Jelinek <jakub@redhat.com>
* sanitizer.def: Add Address Sanitizer builtins.
Rename BUILT_IN_TSAN_READ_* to BUILT_IN_TSAN_READ* and
BUILT_IN_TSAN_WRITE_* to BUILT_IN_TSAN_WRITE*.
* Makefile.in (asan.o): Depend on langhooks.h.
(tsan.o): Depend on asan.h.
* asan.h (initialize_sanitizer_builtins): New prototype.
* asan.c: Include langhooks.h.
(report_error_func): Use builtin_decl_implicit of corresponding
BUILT_IN_ASAN_REPORT_{LOAD,STORE}*.
(asan_init_func): Removed.
(initialize_sanitizer_builtins): New function.
(asan_finish_file): Call it. Use builtin_decl_implicit
on BUILT_IN_ASAN_{INIT,{,UN}REGISTER_GLOBALS}.
(asan_instrument): Call initialize_sanitizer_builtins.
* builtins.def (DEF_SANITIZER_BUILTIN): Change condition to
(flag_asan || flag_tsan).
* tsan.c: Include asan.h and tsan.h.
(get_memory_access_decl): Rename BUILT_IN_TSAN_{READ,WRITE}_*
to BUILT_IN_TSAN_{READ,WRITE}*.
(tsan_pass): Call initialize_sanitizer_builtins.
(tsan_gate, tsan_gate_O0): Don't check if
builtin_decl_implicit_p (BUILT_IN_TSAN_INIT) is true.
(tsan_finish_file): Call initialize_sanitizer_builtins.
* builtin-types.def (BT_FN_VOID_PTR_PTRMODE): New fn type.
2012-12-03 Aldy Hernandez <aldyh@redhat.com>
PR middle-end/55401

View File

@ -2228,13 +2228,13 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
asan.o : asan.c asan.h $(CONFIG_H) $(SYSTEM_H) $(GIMPLE_H) \
output.h coretypes.h $(GIMPLE_PRETTY_PRINT_H) \
tree-iterator.h $(TREE_FLOW_H) $(TREE_PASS_H) \
$(TARGET_H) $(EXPR_H) $(OPTABS_H) $(TM_P_H)
$(TARGET_H) $(EXPR_H) $(OPTABS_H) $(TM_P_H) langhooks.h
tsan.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
$(GIMPLE_H) $(DIAGNOSTIC_H) langhooks.h \
$(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_PASS_H) $(CGRAPH_H) $(GGC_H) \
$(BASIC_BLOCK_H) $(FLAGS_H) $(FUNCTION_H) \
$(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) tree-iterator.h \
intl.h cfghooks.h output.h options.h c-family/c-common.h tsan.h
intl.h cfghooks.h output.h options.h c-family/c-common.h tsan.h asan.h
tree-ssa-tail-merge.o: tree-ssa-tail-merge.c \
$(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(BITMAP_H) \
$(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \

View File

@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "output.h"
#include "tm_p.h"
#include "langhooks.h"
/* AddressSanitizer finds out-of-bounds and use-after-free bugs
with <2x slowdown on average.
@ -485,38 +486,16 @@ asan_protect_global (tree decl)
static tree
report_error_func (bool is_store, int size_in_bytes)
{
tree fn_type;
tree def;
char name[100];
sprintf (name, "__asan_report_%s%d",
is_store ? "store" : "load", size_in_bytes);
fn_type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
def = build_fn_decl (name, fn_type);
TREE_NOTHROW (def) = 1;
DECL_IGNORED_P (def) = 1;
TREE_THIS_VOLATILE (def) = 1; /* Attribute noreturn. Surprise! */
DECL_ATTRIBUTES (def) = tree_cons (get_identifier ("leaf"),
NULL, DECL_ATTRIBUTES (def));
return def;
static enum built_in_function report[2][5]
= { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
BUILT_IN_ASAN_REPORT_LOAD16 },
{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
BUILT_IN_ASAN_REPORT_STORE16 } };
return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
}
/* Construct a function tree for __asan_init(). */
static tree
asan_init_func (void)
{
tree fn_type;
tree def;
fn_type = build_function_type_list (void_type_node, NULL_TREE);
def = build_fn_decl ("__asan_init", fn_type);
TREE_NOTHROW (def) = 1;
DECL_IGNORED_P (def) = 1;
return def;
}
#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1)
#define PROB_ALWAYS (REG_BR_PROB_BASE)
@ -1510,6 +1489,38 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
}
/* Initialize sanitizer.def builtins if the FE hasn't initialized them. */
void
initialize_sanitizer_builtins (void)
{
tree decl;
if (builtin_decl_implicit_p (BUILT_IN_ASAN_INIT))
return;
tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
tree BT_FN_VOID_PTR
= build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
tree BT_FN_VOID_PTR_PTRMODE
= build_function_type_list (void_type_node, ptr_type_node,
build_nonstandard_integer_type (POINTER_SIZE,
1), NULL_TREE);
#undef ATTR_NOTHROW_LEAF_LIST
#define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF
#undef ATTR_NORETURN_NOTHROW_LEAF_LIST
#define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST
#undef DEF_SANITIZER_BUILTIN
#define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \
BUILT_IN_NORMAL, NAME, NULL_TREE); \
set_call_expr_flags (decl, ATTRS); \
set_builtin_decl (ENUM, decl, true);
#include "sanitizer.def"
#undef DEF_SANITIZER_BUILTIN
}
/* Needs to be GTY(()), because cgraph_build_static_cdtor may
invoke ggc_collect. */
static GTY(()) tree asan_ctor_statements;
@ -1525,14 +1536,16 @@ asan_finish_file (void)
struct varpool_node *vnode;
unsigned HOST_WIDE_INT gcount = 0;
append_to_statement_list (build_call_expr (asan_init_func (), 0),
&asan_ctor_statements);
initialize_sanitizer_builtins ();
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;
if (gcount)
{
tree type = asan_global_struct (), var, ctor, decl;
tree type = asan_global_struct (), var, ctor;
tree uptr = build_nonstandard_integer_type (POINTER_SIZE, 1);
tree dtor_statements = NULL_TREE;
vec<constructor_elt, va_gc> *v;
@ -1556,20 +1569,14 @@ asan_finish_file (void)
DECL_INITIAL (var) = ctor;
varpool_assemble_decl (varpool_node_for_decl (var));
type = build_function_type_list (void_type_node, ptr_type_node,
uptr, NULL_TREE);
decl = build_fn_decl ("__asan_register_globals", type);
TREE_NOTHROW (decl) = 1;
DECL_IGNORED_P (decl) = 1;
append_to_statement_list (build_call_expr (decl, 2,
fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS);
append_to_statement_list (build_call_expr (fn, 2,
build_fold_addr_expr (var),
build_int_cst (uptr, gcount)),
&asan_ctor_statements);
decl = build_fn_decl ("__asan_unregister_globals", type);
TREE_NOTHROW (decl) = 1;
DECL_IGNORED_P (decl) = 1;
append_to_statement_list (build_call_expr (decl, 2,
fn = builtin_decl_implicit (BUILT_IN_ASAN_UNREGISTER_GLOBALS);
append_to_statement_list (build_call_expr (fn, 2,
build_fold_addr_expr (var),
build_int_cst (uptr, gcount)),
&dtor_statements);
@ -1600,7 +1607,10 @@ static unsigned int
asan_instrument (void)
{
if (shadow_ptr_types[0] == NULL_TREE)
asan_init_shadow_ptr_types ();
{
asan_init_shadow_ptr_types ();
initialize_sanitizer_builtins ();
}
transform_statements ();
return 0;
}

View File

@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
extern void asan_finish_file (void);
extern rtx asan_emit_stack_protection (rtx, HOST_WIDE_INT *, tree *, int);
extern bool asan_protect_global (tree);
extern void initialize_sanitizer_builtins (void);
/* Alias set for accessing the shadow memory. */
extern alias_set_type asan_shadow_set;

View File

@ -253,6 +253,8 @@ DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_FILEPTR,
BT_INT, BT_INT, BT_FILEPTR)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRMODE_PTR,
BT_VOID, BT_PTRMODE, BT_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE,
BT_VOID, BT_PTR, BT_PTRMODE)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VALIST_REF_VALIST_ARG,
BT_VOID, BT_VALIST_REF, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_2 (BT_FN_LONG_LONG_LONG,

View File

@ -156,7 +156,7 @@ along with GCC; see the file COPYING3. If not see
#define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
true, true, true, ATTRS, true, \
flag_tsan)
(flag_asan || flag_tsan))
/* Define an attribute list for math functions that are normally
"impure" because some of them may write into global memory for

View File

@ -1,3 +1,62 @@
/* This file contains the definitions and documentation for the
Address Sanitizer and Thread Sanitizer builtins used in the GNU compiler.
Copyright (C) 2012 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* Before including this file, you should define a macro:
DEF_SANITIZER_BUILTIN (ENUM, NAME, TYPE, ATTRS)
See builtins.def for details.
The builtins are created by the C-family of FEs in c-family/c-common.c,
for other FEs by asan.c. */
/* Address Sanitizer */
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2, "__asan_report_load2",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4, "__asan_report_load4",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4, "__asan_report_store4",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS,
"__asan_register_globals",
BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNREGISTER_GLOBALS,
"__asan_unregister_globals",
BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
/* Thread Sanitizer */
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_FUNC_ENTRY, "__tsan_func_entry",
@ -6,23 +65,23 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_FUNC_EXIT, "__tsan_func_exit",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VPTR_UPDATE, "__tsan_vptr_update",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_1, "__tsan_read1",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ1, "__tsan_read1",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_2, "__tsan_read2",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ2, "__tsan_read2",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_4, "__tsan_read4",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ4, "__tsan_read4",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_8, "__tsan_read8",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ8, "__tsan_read8",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_16, "__tsan_read16",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ16, "__tsan_read16",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_1, "__tsan_write1",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE1, "__tsan_write1",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_2, "__tsan_write2",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE2, "__tsan_write2",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_4, "__tsan_write4",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE4, "__tsan_write4",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_8, "__tsan_write8",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE8, "__tsan_write8",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_16, "__tsan_write16",
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE16, "__tsan_write16",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)

View File

@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "cgraph.h"
#include "diagnostic.h"
#include "tsan.h"
#include "asan.h"
/* Number of instrumented memory accesses in the current function. */
@ -49,20 +51,20 @@ get_memory_access_decl (bool is_write, unsigned size)
enum built_in_function fcode;
if (size <= 1)
fcode = is_write ? BUILT_IN_TSAN_WRITE_1
: BUILT_IN_TSAN_READ_1;
fcode = is_write ? BUILT_IN_TSAN_WRITE1
: BUILT_IN_TSAN_READ1;
else if (size <= 3)
fcode = is_write ? BUILT_IN_TSAN_WRITE_2
: BUILT_IN_TSAN_READ_2;
fcode = is_write ? BUILT_IN_TSAN_WRITE2
: BUILT_IN_TSAN_READ2;
else if (size <= 7)
fcode = is_write ? BUILT_IN_TSAN_WRITE_4
: BUILT_IN_TSAN_READ_4;
fcode = is_write ? BUILT_IN_TSAN_WRITE4
: BUILT_IN_TSAN_READ4;
else if (size <= 15)
fcode = is_write ? BUILT_IN_TSAN_WRITE_8
: BUILT_IN_TSAN_READ_8;
fcode = is_write ? BUILT_IN_TSAN_WRITE8
: BUILT_IN_TSAN_READ8;
else
fcode = is_write ? BUILT_IN_TSAN_WRITE_16
: BUILT_IN_TSAN_READ_16;
fcode = is_write ? BUILT_IN_TSAN_WRITE16
: BUILT_IN_TSAN_READ16;
return builtin_decl_implicit (fcode);
}
@ -285,6 +287,7 @@ instrument_func_exit (void)
static unsigned
tsan_pass (void)
{
initialize_sanitizer_builtins ();
if (instrument_memory_accesses ())
{
instrument_func_entry ();
@ -298,8 +301,7 @@ tsan_pass (void)
static bool
tsan_gate (void)
{
return flag_tsan != 0
&& builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
return flag_tsan != 0;
}
/* Inserts __tsan_init () into the list of CTORs. */
@ -307,11 +309,10 @@ tsan_gate (void)
void
tsan_finish_file (void)
{
tree ctor_statements;
tree init_decl;
tree ctor_statements = NULL_TREE;
ctor_statements = NULL_TREE;
init_decl = builtin_decl_implicit (BUILT_IN_TSAN_INIT);
initialize_sanitizer_builtins ();
tree init_decl = builtin_decl_implicit (BUILT_IN_TSAN_INIT);
append_to_statement_list (build_call_expr (init_decl, 0),
&ctor_statements);
cgraph_build_static_cdtor ('I', ctor_statements,
@ -343,8 +344,7 @@ struct gimple_opt_pass pass_tsan =
static bool
tsan_gate_O0 (void)
{
return flag_tsan != 0 && !optimize
&& builtin_decl_implicit_p (BUILT_IN_TSAN_INIT);
return flag_tsan != 0 && !optimize;
}
struct gimple_opt_pass pass_tsan_O0 =