I've attached updated patch (also reuploaded
https://codereview.appspot.com/280140043).
Fixed ChangeLog.
Added invoke.texi.
Fixed style issues.

The function is defined only in kernel at the moment. Here is my patch:
https://github.com/dvyukov/linux/commit/f86eda0c895c47ea02ee37e981aeade7b03014d7
It is not mailed yet, for kernel asan people requested submit to gcc
first, then to kernel.

It will also be supported by libsanitizer later (Kostya?). But it is
not yet there.

Regarding plugins, we did tsan first as gcc plugin. It was difficult
to support, difficult to use, difficult to distribute. I maintain this
patch for a month, two people complained that it does not build
(because they synched to slightly different revisions).
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 231234)
+++ ChangeLog	(working copy)
@@ -1,3 +1,15 @@
+2015-12-03  Dmitry Vyukov  <dvyu...@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-03  Evandro Menezes  <e.mene...@samsung.com>
 
 	* config/aarch64/aarch64-cores.def: Use the Exynos M1 cost model.
@@ -360,7 +372,6 @@
 	* tree-ssa-structalias.c (find_func_aliases_for_builtin_call)
 	(find_func_clobbers, ipa_pta_execute): Handle BUILT_IN_GOACC_PARALLEL.
 
->>>>>>> .r231221
 2015-12-02  Segher Boessenkool  <seg...@kernel.crashing.org>
 
 	* config/rs6000/rs6000.md (cstore_si_as_di): New expander.
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 231234)
+++ Makefile.in	(working copy)
@@ -1427,6 +1427,7 @@
 	tsan.o \
 	ubsan.o \
 	sanopt.o \
+	sancov.o \
 	tree-call-cdce.o \
 	tree-cfg.o \
 	tree-cfgcleanup.o \
@@ -2400,6 +2401,7 @@
   $(srcdir)/ubsan.c \
   $(srcdir)/tsan.c \
   $(srcdir)/sanopt.c \
+  $(srcdir)/sancov.c \
   $(srcdir)/ipa-devirt.c \
   $(srcdir)/internal-fn.h \
   @all_gtfiles@
Index: builtins.def
===================================================================
--- builtins.def	(revision 231234)
+++ builtins.def	(working copy)
@@ -210,7 +210,8 @@
   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)  \
Index: common.opt
===================================================================
--- common.opt	(revision 231234)
+++ common.opt	(working copy)
@@ -225,6 +225,11 @@
 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
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 231234)
+++ doc/invoke.texi	(working copy)
@@ -6135,6 +6135,11 @@
 @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
Index: passes.def
===================================================================
--- passes.def	(revision 231234)
+++ passes.def	(working copy)
@@ -237,6 +237,7 @@
       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 @@
          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 @@
   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);
Index: sancov.c
===================================================================
--- sancov.c	(revision 0)
+++ sancov.c	(working copy)
@@ -0,0 +1,109 @@
+/* Code coverage instrumentation for fuzzing.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   Contributed by Dmitry Vyukov <dvyu...@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)
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+  gimple *stmt, *f;
+  static bool inited;
+
+  if (!inited)
+    {
+      inited = true;
+      initialize_sanitizer_builtins ();
+    }
+
+  /* Insert callback into beginning of every BB. */
+  FOR_EACH_BB_FN (bb, fun)
+    {
+      gsi = gsi_after_labels (bb);
+      if (gsi_end_p (gsi))
+        continue;
+      f = gimple_build_call (builtin_decl_implicit (
+                             BUILT_IN_SANITIZER_COV_TRACE_PC), 0);
+      gimple_set_location (f, gimple_location (stmt));
+      gsi_insert_before (&gsi, f, 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);
+}
Index: sanitizer.def
===================================================================
--- sanitizer.def	(revision 231234)
+++ sanitizer.def	(working copy)
@@ -510,3 +510,8 @@
 		      "__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)
Index: testsuite/gcc.dg/sancov/asan.c
===================================================================
--- testsuite/gcc.dg/sancov/asan.c	(revision 0)
+++ testsuite/gcc.dg/sancov/asan.c	(working copy)
@@ -0,0 +1,21 @@
+/* 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" } */
+
+void notailcall ();
+
+void foo(volatile int *a, int *b)
+{
+  *a = 1;
+  if (*b)
+    *a = 2;
+  notailcall ();
+}
+
+/* { dg-final { scan-assembler-times "call	__sanitizer_cov_trace_pc" 4 } } */
+/* { dg-final { scan-assembler-times "call	__asan_report_load4" 1 } } */
+/* { dg-final { scan-assembler-times "call	__asan_report_store4" 1 } } */
Index: testsuite/gcc.dg/sancov/basic0.c
===================================================================
--- testsuite/gcc.dg/sancov/basic0.c	(revision 0)
+++ testsuite/gcc.dg/sancov/basic0.c	(working copy)
@@ -0,0 +1,12 @@
+/* Basic test on number of inserted callbacks.  */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc" } */
+
+void notailcall ();
+
+void foo(void)
+{
+  notailcall ();
+}
+
+/* { dg-final { scan-assembler-times "call	__sanitizer_cov_trace_pc" 1 } } */
Index: testsuite/gcc.dg/sancov/basic1.c
===================================================================
--- testsuite/gcc.dg/sancov/basic1.c	(revision 0)
+++ testsuite/gcc.dg/sancov/basic1.c	(working copy)
@@ -0,0 +1,15 @@
+/* Basic test on number of inserted callbacks.  */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc" } */
+
+void notailcall ();
+
+void foo (int *a, int *b, int *c)
+{
+  *a = 1;
+  if (*b)
+    *c = 2;
+  notailcall ();
+}
+
+/* { dg-final { scan-assembler-times "call	__sanitizer_cov_trace_pc" 3 } } */
Index: testsuite/gcc.dg/sancov/basic2.c
===================================================================
--- testsuite/gcc.dg/sancov/basic2.c	(revision 0)
+++ testsuite/gcc.dg/sancov/basic2.c	(working copy)
@@ -0,0 +1,17 @@
+/* Basic test on number of inserted callbacks.  */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc" } */
+
+void notailcall ();
+
+void foo(int *a, int *b, int *c, int *d)
+{
+  *a = 1;
+  if (*b)
+    *c = 2;
+  else
+    *d = 3;
+  notailcall ();
+}
+
+/* { dg-final { scan-assembler-times "call	__sanitizer_cov_trace_pc" 4 } } */
Index: testsuite/gcc.dg/sancov/sancov.exp
===================================================================
--- testsuite/gcc.dg/sancov/sancov.exp	(revision 0)
+++ testsuite/gcc.dg/sancov/sancov.exp	(working copy)
@@ -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
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 231234)
+++ tree-pass.h	(working copy)
@@ -351,6 +351,8 @@
 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);

Reply via email to