summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authordvyukov <dvyukov@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-04 18:27:54 +0000
committerdvyukov <dvyukov@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-04 18:27:54 +0000
commitd29e939c63b71c839aeb122e8d8a8a2a2d062778 (patch)
tree9be0f083fcd490b1940dc33ac1c11dc8d4632fd6 /gcc
parentdd8aabc9af55ca8a5f6e3d5e54625adf10984ff8 (diff)
downloadgcc-d29e939c63b71c839aeb122e8d8a8a2a2d062778.tar.gz
Add fuzzing coverage support
* sancov.c: New file. * Makefile.in (OBJS): Add sancov.o. * invoke.texi (-fsanitize-coverage=trace-pc): Describe. * passes.def (sancov_pass): Add. * tree-pass.h (sancov_pass): Add. * common.opt (-fsanitize-coverage=trace-pc): Add. * sanitizer.def (BUILT_IN_SANITIZER_COV_TRACE_PC): Add. * builtins.def (DEF_SANITIZER_BUILTIN): Enable for flag_sanitize_coverage. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231296 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/builtins.def3
-rw-r--r--gcc/common.opt5
-rw-r--r--gcc/doc/invoke.texi5
-rw-r--r--gcc/passes.def3
-rw-r--r--gcc/sancov.c108
-rw-r--r--gcc/sanitizer.def5
-rw-r--r--gcc/testsuite/gcc.dg/sancov/asan.c18
-rw-r--r--gcc/testsuite/gcc.dg/sancov/basic0.c9
-rw-r--r--gcc/testsuite/gcc.dg/sancov/basic1.c12
-rw-r--r--gcc/testsuite/gcc.dg/sancov/basic2.c14
-rw-r--r--gcc/testsuite/gcc.dg/sancov/sancov.exp37
-rw-r--r--gcc/tree-pass.h2
14 files changed, 234 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 39420b13165..62c6b96abc8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2015-12-04 Dmitry Vyukov <dvyukov@google.com>
+
+ * sancov.c: New file.
+ * Makefile.in (OBJS): Add sancov.o.
+ * invoke.texi (-fsanitize-coverage=trace-pc): Describe.
+ * passes.def (sancov_pass): Add.
+ * tree-pass.h (sancov_pass): Add.
+ * common.opt (-fsanitize-coverage=trace-pc): Add.
+ * sanitizer.def (BUILT_IN_SANITIZER_COV_TRACE_PC): Add.
+ * builtins.def (DEF_SANITIZER_BUILTIN): Enable for
+ flag_sanitize_coverage.
+
2015-12-04 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/65958
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d2d09f64f5f..1f698798aa2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1427,6 +1427,7 @@ OBJS = \
tsan.o \
ubsan.o \
sanopt.o \
+ sancov.o \
tree-call-cdce.o \
tree-cfg.o \
tree-cfgcleanup.o \
@@ -2400,6 +2401,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/ubsan.c \
$(srcdir)/tsan.c \
$(srcdir)/sanopt.c \
+ $(srcdir)/sancov.c \
$(srcdir)/ipa-devirt.c \
$(srcdir)/internal-fn.h \
@all_gtfiles@
diff --git a/gcc/builtins.def b/gcc/builtins.def
index ed850df2d01..238f38fd3dd 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -210,7 +210,8 @@ along with GCC; see the file COPYING3. If not see
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
true, true, true, ATTRS, true, \
(flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
- | SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
+ | SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT) \
+ || flag_sanitize_coverage))
#undef DEF_CILKPLUS_BUILTIN
#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
diff --git a/gcc/common.opt b/gcc/common.opt
index e593631b5f2..1de4c24fbc6 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -225,6 +225,11 @@ unsigned int flag_sanitize
Variable
unsigned int flag_sanitize_recover = SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS
+fsanitize-coverage=trace-pc
+Common Report Var(flag_sanitize_coverage)
+Enable coverage-guided fuzzing code instrumentation.
+Inserts call to __sanitizer_cov_trace_pc into every basic block.
+
; Flag whether a prefix has been added to dump_base_name
Variable
bool dump_base_name_prefixed = false
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9ce37bbbb44..52560313881 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6136,6 +6136,11 @@ a @code{libubsan} library routine. The advantage of this is that the
@code{libubsan} library is not needed and is not linked in, so this
is usable even in freestanding environments.
+@item -fsanitize-coverage=trace-pc
+@opindex fsanitize-coverage=trace-pc
+Enable coverage-guided fuzzing code instrumentation.
+Inserts call to __sanitizer_cov_trace_pc into every basic block.
+
@item -fcheck-pointer-bounds
@opindex fcheck-pointer-bounds
@opindex fno-check-pointer-bounds
diff --git a/gcc/passes.def b/gcc/passes.def
index 28cb4c1cf1f..624d121fe47 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -237,6 +237,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_split_crit_edges);
NEXT_PASS (pass_pre);
NEXT_PASS (pass_sink_code);
+ NEXT_PASS (pass_sancov);
NEXT_PASS (pass_asan);
NEXT_PASS (pass_tsan);
/* Pass group that runs when 1) enabled, 2) there are loops
@@ -346,6 +347,7 @@ along with GCC; see the file COPYING3. If not see
to forward object-size and builtin folding results properly. */
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_dce);
+ NEXT_PASS (pass_sancov);
NEXT_PASS (pass_asan);
NEXT_PASS (pass_tsan);
/* ??? We do want some kind of loop invariant motion, but we possibly
@@ -369,6 +371,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_lower_vaarg);
NEXT_PASS (pass_lower_vector);
NEXT_PASS (pass_lower_complex_O0);
+ NEXT_PASS (pass_sancov_O0);
NEXT_PASS (pass_asan_O0);
NEXT_PASS (pass_tsan_O0);
NEXT_PASS (pass_sanopt);
diff --git a/gcc/sancov.c b/gcc/sancov.c
new file mode 100644
index 00000000000..edc1fbcf31b
--- /dev/null
+++ b/gcc/sancov.c
@@ -0,0 +1,108 @@
+/* Code coverage instrumentation for fuzzing.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ Contributed by Dmitry Vyukov <dvyukov@google.com>
+
+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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple.h"
+#include "basic-block.h"
+#include "options.h"
+#include "flags.h"
+#include "stmt.h"
+#include "gimple-iterator.h"
+#include "tree-cfg.h"
+#include "tree-pass.h"
+#include "tree-iterator.h"
+#include "asan.h"
+
+namespace {
+
+unsigned
+sancov_pass (function *fun)
+{
+ initialize_sanitizer_builtins ();
+
+ /* Insert callback into beginning of every BB. */
+ tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_PC);
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, fun)
+ {
+ gimple_stmt_iterator gsi = gsi_after_labels (bb);
+ if (gsi_end_p (gsi))
+ continue;
+ gimple *stmt = gsi_stmt (gsi);
+ gimple *gcall = gimple_build_call (fndecl, 0);
+ gimple_set_location (gcall, gimple_location (stmt));
+ gsi_insert_before (&gsi, gcall, GSI_SAME_STMT);
+ }
+ return 0;
+}
+
+template <bool O0> class pass_sancov : public gimple_opt_pass
+{
+public:
+ pass_sancov (gcc::context *ctxt) : gimple_opt_pass (data, ctxt) {}
+
+ static const pass_data data;
+ opt_pass *
+ clone ()
+ {
+ return new pass_sancov<O0> (m_ctxt);
+ }
+ virtual bool
+ gate (function *)
+ {
+ return flag_sanitize_coverage && (!O0 || !optimize);
+ }
+ virtual unsigned int
+ execute (function *fun)
+ {
+ return sancov_pass (fun);
+ }
+}; // class pass_sancov
+
+template <bool O0>
+const pass_data pass_sancov<O0>::data = {
+ GIMPLE_PASS, /* type */
+ O0 ? "sancov_O0" : "sancov", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ (PROP_cfg), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_update_ssa, /* todo_flags_finish */
+};
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_sancov (gcc::context *ctxt)
+{
+ return new pass_sancov<false> (ctxt);
+}
+
+gimple_opt_pass *
+make_pass_sancov_O0 (gcc::context *ctxt)
+{
+ return new pass_sancov<true> (ctxt);
+}
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 73e41a051e2..2780dd95cf0 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -510,3 +510,8 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT,
"__ubsan_handle_dynamic_type_cache_miss_abort",
BT_FN_VOID_PTR_PTR_PTR,
ATTR_COLD_NOTHROW_LEAF_LIST)
+
+/* Sanitizer coverage */
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_PC,
+ "__sanitizer_cov_trace_pc",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
diff --git a/gcc/testsuite/gcc.dg/sancov/asan.c b/gcc/testsuite/gcc.dg/sancov/asan.c
new file mode 100644
index 00000000000..f566ed2cd4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sancov/asan.c
@@ -0,0 +1,18 @@
+/* Test coverage/asan interaction:
+ - coverage instruments __asan_init ctor (thus 4 covarage callbacks)
+ - coverage does not instrument asan-emitted basic blocks
+ - asan considers coverage callback as "nonfreeing" (thus 1 asan store
+ callback. */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc -fsanitize=address -fdump-tree-optimized" } */
+
+void foo(volatile int *a, int *b)
+{
+ *a = 1;
+ if (*b)
+ *a = 2;
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin___sanitizer_cov_trace_pc \\(\\)" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4 \\(" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store4 \\(" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/sancov/basic0.c b/gcc/testsuite/gcc.dg/sancov/basic0.c
new file mode 100644
index 00000000000..af69b2d12ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sancov/basic0.c
@@ -0,0 +1,9 @@
+/* Basic test on number of inserted callbacks. */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc -fdump-tree-optimized" } */
+
+void foo(void)
+{
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin___sanitizer_cov_trace_pc \\(\\)" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/sancov/basic1.c b/gcc/testsuite/gcc.dg/sancov/basic1.c
new file mode 100644
index 00000000000..e0ae5b4d7b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sancov/basic1.c
@@ -0,0 +1,12 @@
+/* Basic test on number of inserted callbacks. */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc -fdump-tree-optimized" } */
+
+void foo (int *a, int *b, int *c)
+{
+ *a = 1;
+ if (*b)
+ *c = 2;
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin___sanitizer_cov_trace_pc \\(\\)" 3 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/sancov/basic2.c b/gcc/testsuite/gcc.dg/sancov/basic2.c
new file mode 100644
index 00000000000..ac2ec785091
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sancov/basic2.c
@@ -0,0 +1,14 @@
+/* Basic test on number of inserted callbacks. */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc -fdump-tree-optimized" } */
+
+void foo(int *a, int *b, int *c, int *d)
+{
+ *a = 1;
+ if (*b)
+ *c = 2;
+ else
+ *d = 3;
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin___sanitizer_cov_trace_pc \\(\\)" 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/sancov/sancov.exp b/gcc/testsuite/gcc.dg/sancov/sancov.exp
new file mode 100644
index 00000000000..e36d743a3cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sancov/sancov.exp
@@ -0,0 +1,37 @@
+# Copyright (C) 2015 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/>.
+
+load_lib gcc-dg.exp
+load_lib torture-options.exp
+
+dg-init
+torture-init
+set-torture-options [list \
+ { -O0 } \
+ { -O1 } \
+ { -O2 } \
+ { -O3 } \
+ { -O0 -g } \
+ { -O1 -g } \
+ { -O2 -g } \
+ { -O3 -g } ]
+
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] "" ""
+
+torture-finish
+dg-finish
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 97049183451..e1cbce923e4 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -351,6 +351,8 @@ extern gimple_opt_pass *make_pass_asan (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_asan_O0 (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_tsan (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_tsan_O0 (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sancov (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sancov_O0 (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_lower_cf (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_refactor_eh (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_lower_eh (gcc::context *ctxt);