1 /* Code coverage instrumentation for fuzzing. 2 Copyright (C) 2015-2017 Free Software Foundation, Inc. 3 Contributed by Dmitry Vyukov <dvyukov@google.com> 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "backend.h" 25 #include "tree.h" 26 #include "gimple.h" 27 #include "basic-block.h" 28 #include "options.h" 29 #include "flags.h" 30 #include "stmt.h" 31 #include "gimple-iterator.h" 32 #include "tree-cfg.h" 33 #include "tree-pass.h" 34 #include "tree-iterator.h" 35 #include "asan.h" 36 37 namespace { 38 39 unsigned 40 sancov_pass (function *fun) 41 { 42 initialize_sanitizer_builtins (); 43 44 /* Insert callback into beginning of every BB. */ 45 tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_PC); 46 basic_block bb; 47 FOR_EACH_BB_FN (bb, fun) 48 { 49 gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb); 50 if (gsi_end_p (gsi)) 51 continue; 52 gimple *stmt = gsi_stmt (gsi); 53 gimple *gcall = gimple_build_call (fndecl, 0); 54 gimple_set_location (gcall, gimple_location (stmt)); 55 gsi_insert_before (&gsi, gcall, GSI_SAME_STMT); 56 } 57 return 0; 58 } 59 60 template <bool O0> class pass_sancov : public gimple_opt_pass 61 { 62 public: 63 pass_sancov (gcc::context *ctxt) : gimple_opt_pass (data, ctxt) {} 64 65 static const pass_data data; 66 opt_pass * 67 clone () 68 { 69 return new pass_sancov<O0> (m_ctxt); 70 } 71 virtual bool 72 gate (function *) 73 { 74 return flag_sanitize_coverage && (!O0 || !optimize); 75 } 76 virtual unsigned int 77 execute (function *fun) 78 { 79 return sancov_pass (fun); 80 } 81 }; // class pass_sancov 82 83 template <bool O0> 84 const pass_data pass_sancov<O0>::data = { 85 GIMPLE_PASS, /* type */ 86 O0 ? "sancov_O0" : "sancov", /* name */ 87 OPTGROUP_NONE, /* optinfo_flags */ 88 TV_NONE, /* tv_id */ 89 (PROP_cfg), /* properties_required */ 90 0, /* properties_provided */ 91 0, /* properties_destroyed */ 92 0, /* todo_flags_start */ 93 TODO_update_ssa, /* todo_flags_finish */ 94 }; 95 96 } // anon namespace 97 98 gimple_opt_pass * 99 make_pass_sancov (gcc::context *ctxt) 100 { 101 return new pass_sancov<false> (ctxt); 102 } 103 104 gimple_opt_pass * 105 make_pass_sancov_O0 (gcc::context *ctxt) 106 { 107 return new pass_sancov<true> (ctxt); 108 } 109