On Wed, Dec 2, 2015 at 5:47 PM, Bernd Schmidt <bschm...@redhat.com> wrote: > On 12/02/2015 05:10 PM, Dmitry Vyukov wrote: >> >> ping > > > I do not see the original submission in my archives.
That's strange. I don't see it in gcc-patches archives as well. The original email contained a plain-text patch attachment. Attaching it again. > This one comes too late > to make it into gcc-6. I can make some initial comments. > >>>> This patch adds support for coverage-guided fuzzing: >>>> https://codereview.appspot.com/280140043 > > > Please send patches with the mail (the best method is usually a text/plain > attachment) so that they can be quoted. > > From what I can tell this is relatively straight-forward. You'll want to fix > a number of issues with coding style (formatting, and lack of function > comments). > > There's no documentation in invoke.texi. Will fix. Can you point to some concrete coding style violations (besides function comments)? > We seem to have no established process for deciding whether we want a new > feature. I am not sure how to approach such a question, and it comes up > quite often. Somehow the default answer usually seems to be to accept > anything.
Index: ChangeLog =================================================================== --- ChangeLog (revision 231000) +++ ChangeLog (working copy) @@ -1,3 +1,13 @@ +2015-11-27 Dmitry Vyukov <dvyu...@google.com> + + * sancov.c: add file. + * Makefile.in: add sancov.c. + * passes.def: add sancov pass. + * tree-pass.h: add sancov pass. + * common.opt: add -fsanitize-coverage=trace-pc flag. + * sanitizer.def: add __sanitizer_cov_trace_pc builtin. + * builtins.def: enable sanitizer builtins when coverage is enabled. + 2015-11-27 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/68552 Index: Makefile.in =================================================================== --- Makefile.in (revision 231000) +++ Makefile.in (working copy) @@ -1426,6 +1426,7 @@ tsan.o \ ubsan.o \ sanopt.o \ + sancov.o \ tree-call-cdce.o \ tree-cfg.o \ tree-cfgcleanup.o \ @@ -2399,6 +2400,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 231000) +++ 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 231000) +++ 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 support. +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: passes.def =================================================================== --- passes.def (revision 231000) +++ 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,116 @@ +/* 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_start_bb (bb); + stmt = gsi_stmt (gsi); + while (stmt && dyn_cast <glabel *> (stmt)) + { + gsi_next (&gsi); + stmt = gsi_stmt (gsi); + } + if (!stmt) + continue; + f = gimple_build_call (builtin_decl_implicit (BUILT_IN_SANCOV_TRACE), 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: + static pass_data pd () + { + static const pass_data 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 */ + }; + return data; + } + + pass_sancov (gcc::context *ctxt) + : gimple_opt_pass (pd(), ctxt) + {} + + 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 + +} // 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 231000) +++ sanitizer.def (working copy) @@ -510,3 +510,7 @@ "__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_SANCOV_TRACE, "__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 231000) +++ 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);