xref: /dflybsd-src/contrib/gcc-8.0/gcc/sancov.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Code coverage instrumentation for fuzzing.
2*38fd1498Szrj    Copyright (C) 2015-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Dmitry Vyukov <dvyukov@google.com> and
4*38fd1498Szrj    Wish Wu <wishwu007@gmail.com>
5*38fd1498Szrj 
6*38fd1498Szrj This file is part of GCC.
7*38fd1498Szrj 
8*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
9*38fd1498Szrj the terms of the GNU General Public License as published by the Free
10*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
11*38fd1498Szrj version.
12*38fd1498Szrj 
13*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*38fd1498Szrj for more details.
17*38fd1498Szrj 
18*38fd1498Szrj You should have received a copy of the GNU General Public License
19*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
20*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
21*38fd1498Szrj 
22*38fd1498Szrj #include "config.h"
23*38fd1498Szrj #include "system.h"
24*38fd1498Szrj #include "coretypes.h"
25*38fd1498Szrj #include "backend.h"
26*38fd1498Szrj #include "tree.h"
27*38fd1498Szrj #include "gimple.h"
28*38fd1498Szrj #include "basic-block.h"
29*38fd1498Szrj #include "options.h"
30*38fd1498Szrj #include "flags.h"
31*38fd1498Szrj #include "memmodel.h"
32*38fd1498Szrj #include "tm_p.h"
33*38fd1498Szrj #include "stmt.h"
34*38fd1498Szrj #include "gimple-iterator.h"
35*38fd1498Szrj #include "gimple-builder.h"
36*38fd1498Szrj #include "tree-cfg.h"
37*38fd1498Szrj #include "tree-pass.h"
38*38fd1498Szrj #include "tree-iterator.h"
39*38fd1498Szrj #include "fold-const.h"
40*38fd1498Szrj #include "stringpool.h"
41*38fd1498Szrj #include "attribs.h"
42*38fd1498Szrj #include "output.h"
43*38fd1498Szrj #include "cgraph.h"
44*38fd1498Szrj #include "asan.h"
45*38fd1498Szrj 
46*38fd1498Szrj namespace {
47*38fd1498Szrj 
48*38fd1498Szrj /* Instrument one comparison operation, which compares lhs and rhs.
49*38fd1498Szrj    Call the instrumentation function with the comparison operand.
50*38fd1498Szrj    For integral comparisons if exactly one of the comparison operands is
51*38fd1498Szrj    constant, call __sanitizer_cov_trace_const_cmp* instead of
52*38fd1498Szrj    __sanitizer_cov_trace_cmp*.  */
53*38fd1498Szrj 
54*38fd1498Szrj static void
instrument_comparison(gimple_stmt_iterator * gsi,tree lhs,tree rhs)55*38fd1498Szrj instrument_comparison (gimple_stmt_iterator *gsi, tree lhs, tree rhs)
56*38fd1498Szrj {
57*38fd1498Szrj   tree type = TREE_TYPE (lhs);
58*38fd1498Szrj   enum built_in_function fncode = END_BUILTINS;
59*38fd1498Szrj   tree to_type = NULL_TREE;
60*38fd1498Szrj   bool c = false;
61*38fd1498Szrj 
62*38fd1498Szrj   if (INTEGRAL_TYPE_P (type))
63*38fd1498Szrj     {
64*38fd1498Szrj       c = (is_gimple_min_invariant (lhs)
65*38fd1498Szrj 	   ^ is_gimple_min_invariant (rhs));
66*38fd1498Szrj       switch (int_size_in_bytes (type))
67*38fd1498Szrj 	{
68*38fd1498Szrj 	case 1:
69*38fd1498Szrj       	  fncode = c ? BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP1
70*38fd1498Szrj 		     : BUILT_IN_SANITIZER_COV_TRACE_CMP1;
71*38fd1498Szrj 	  to_type = unsigned_char_type_node;
72*38fd1498Szrj 	  break;
73*38fd1498Szrj 	case 2:
74*38fd1498Szrj       	  fncode = c ? BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP2
75*38fd1498Szrj 		     : BUILT_IN_SANITIZER_COV_TRACE_CMP2;
76*38fd1498Szrj 	  to_type = uint16_type_node;
77*38fd1498Szrj 	  break;
78*38fd1498Szrj 	case 4:
79*38fd1498Szrj       	  fncode = c ? BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP4
80*38fd1498Szrj 		     : BUILT_IN_SANITIZER_COV_TRACE_CMP4;
81*38fd1498Szrj 	  to_type = uint32_type_node;
82*38fd1498Szrj 	  break;
83*38fd1498Szrj 	default:
84*38fd1498Szrj       	  fncode = c ? BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP8
85*38fd1498Szrj 		     : BUILT_IN_SANITIZER_COV_TRACE_CMP8;
86*38fd1498Szrj 	  to_type = uint64_type_node;
87*38fd1498Szrj 	  break;
88*38fd1498Szrj 	}
89*38fd1498Szrj     }
90*38fd1498Szrj   else if (SCALAR_FLOAT_TYPE_P (type))
91*38fd1498Szrj     {
92*38fd1498Szrj       if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
93*38fd1498Szrj 	{
94*38fd1498Szrj       	  fncode = BUILT_IN_SANITIZER_COV_TRACE_CMPF;
95*38fd1498Szrj 	  to_type = float_type_node;
96*38fd1498Szrj 	}
97*38fd1498Szrj       else if (TYPE_MODE (type) == TYPE_MODE (double_type_node))
98*38fd1498Szrj 	{
99*38fd1498Szrj       	  fncode = BUILT_IN_SANITIZER_COV_TRACE_CMPD;
100*38fd1498Szrj 	  to_type = double_type_node;
101*38fd1498Szrj 	}
102*38fd1498Szrj     }
103*38fd1498Szrj 
104*38fd1498Szrj   if (to_type != NULL_TREE)
105*38fd1498Szrj     {
106*38fd1498Szrj       gimple_seq seq = NULL;
107*38fd1498Szrj 
108*38fd1498Szrj       if (!useless_type_conversion_p (to_type, type))
109*38fd1498Szrj 	{
110*38fd1498Szrj 	  if (TREE_CODE (lhs) == INTEGER_CST)
111*38fd1498Szrj 	    lhs = fold_convert (to_type, lhs);
112*38fd1498Szrj 	  else
113*38fd1498Szrj 	    {
114*38fd1498Szrj 	      gimple_seq_add_stmt (&seq, build_type_cast (to_type, lhs));
115*38fd1498Szrj 	      lhs = gimple_assign_lhs (gimple_seq_last_stmt (seq));
116*38fd1498Szrj 	    }
117*38fd1498Szrj 
118*38fd1498Szrj 	  if (TREE_CODE (rhs) == INTEGER_CST)
119*38fd1498Szrj 	    rhs = fold_convert (to_type, rhs);
120*38fd1498Szrj 	  else
121*38fd1498Szrj 	    {
122*38fd1498Szrj 	      gimple_seq_add_stmt (&seq, build_type_cast (to_type, rhs));
123*38fd1498Szrj 	      rhs = gimple_assign_lhs (gimple_seq_last_stmt (seq));
124*38fd1498Szrj 	    }
125*38fd1498Szrj 	}
126*38fd1498Szrj 
127*38fd1498Szrj       if (c && !is_gimple_min_invariant (lhs))
128*38fd1498Szrj 	std::swap (lhs, rhs);
129*38fd1498Szrj 
130*38fd1498Szrj       tree fndecl = builtin_decl_implicit (fncode);
131*38fd1498Szrj       gimple *gcall = gimple_build_call (fndecl, 2, lhs, rhs);
132*38fd1498Szrj       gimple_seq_add_stmt (&seq, gcall);
133*38fd1498Szrj 
134*38fd1498Szrj       gimple_seq_set_location (seq, gimple_location (gsi_stmt (*gsi)));
135*38fd1498Szrj       gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
136*38fd1498Szrj     }
137*38fd1498Szrj }
138*38fd1498Szrj 
139*38fd1498Szrj /* Instrument switch statement.  Call __sanitizer_cov_trace_switch with
140*38fd1498Szrj    the value of the index and array that contains number of case values,
141*38fd1498Szrj    the bitsize of the index and the case values converted to uint64_t.  */
142*38fd1498Szrj 
143*38fd1498Szrj static void
instrument_switch(gimple_stmt_iterator * gsi,gimple * stmt,function * fun)144*38fd1498Szrj instrument_switch (gimple_stmt_iterator *gsi, gimple *stmt, function *fun)
145*38fd1498Szrj {
146*38fd1498Szrj   gswitch *switch_stmt = as_a<gswitch *> (stmt);
147*38fd1498Szrj   tree index = gimple_switch_index (switch_stmt);
148*38fd1498Szrj   HOST_WIDE_INT size_in_bytes = int_size_in_bytes (TREE_TYPE (index));
149*38fd1498Szrj   if (size_in_bytes == -1 || size_in_bytes > 8)
150*38fd1498Szrj     return;
151*38fd1498Szrj 
152*38fd1498Szrj   location_t loc = gimple_location (stmt);
153*38fd1498Szrj   unsigned i, n = gimple_switch_num_labels (switch_stmt), num = 0;
154*38fd1498Szrj   for (i = 1; i < n; ++i)
155*38fd1498Szrj     {
156*38fd1498Szrj       tree label = gimple_switch_label (switch_stmt, i);
157*38fd1498Szrj 
158*38fd1498Szrj       tree low_case = CASE_LOW (label);
159*38fd1498Szrj       if (low_case != NULL_TREE)
160*38fd1498Szrj 	num++;
161*38fd1498Szrj 
162*38fd1498Szrj       tree high_case = CASE_HIGH (label);
163*38fd1498Szrj       if (high_case != NULL_TREE)
164*38fd1498Szrj 	num++;
165*38fd1498Szrj     }
166*38fd1498Szrj 
167*38fd1498Szrj   tree case_array_type
168*38fd1498Szrj    = build_array_type (build_type_variant (uint64_type_node, 1, 0),
169*38fd1498Szrj 		       build_index_type (size_int (num + 2 - 1)));
170*38fd1498Szrj 
171*38fd1498Szrj   char name[64];
172*38fd1498Szrj   static size_t case_array_count = 0;
173*38fd1498Szrj   ASM_GENERATE_INTERNAL_LABEL (name, "LCASEARRAY", case_array_count++);
174*38fd1498Szrj   tree case_array_var = build_decl (loc, VAR_DECL, get_identifier (name),
175*38fd1498Szrj 				    case_array_type);
176*38fd1498Szrj   TREE_STATIC (case_array_var) = 1;
177*38fd1498Szrj   TREE_PUBLIC (case_array_var) = 0;
178*38fd1498Szrj   TREE_CONSTANT (case_array_var) = 1;
179*38fd1498Szrj   TREE_READONLY (case_array_var) = 1;
180*38fd1498Szrj   DECL_EXTERNAL (case_array_var) = 0;
181*38fd1498Szrj   DECL_ARTIFICIAL (case_array_var) = 1;
182*38fd1498Szrj   DECL_IGNORED_P (case_array_var) = 1;
183*38fd1498Szrj 
184*38fd1498Szrj   vec <constructor_elt, va_gc> *v = NULL;
185*38fd1498Szrj   vec_alloc (v, num + 2);
186*38fd1498Szrj   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
187*38fd1498Szrj 			  build_int_cst (uint64_type_node, num));
188*38fd1498Szrj   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
189*38fd1498Szrj 			  build_int_cst (uint64_type_node,
190*38fd1498Szrj 					 size_in_bytes * BITS_PER_UNIT));
191*38fd1498Szrj   for (i = 1; i < n; ++i)
192*38fd1498Szrj     {
193*38fd1498Szrj       tree label = gimple_switch_label (switch_stmt, i);
194*38fd1498Szrj 
195*38fd1498Szrj       tree low_case = CASE_LOW (label);
196*38fd1498Szrj       if (low_case != NULL_TREE)
197*38fd1498Szrj 	CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
198*38fd1498Szrj 				fold_convert (uint64_type_node, low_case));
199*38fd1498Szrj 
200*38fd1498Szrj       tree high_case = CASE_HIGH (label);
201*38fd1498Szrj       if (high_case != NULL_TREE)
202*38fd1498Szrj 	CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
203*38fd1498Szrj 				fold_convert (uint64_type_node, high_case));
204*38fd1498Szrj     }
205*38fd1498Szrj   tree ctor = build_constructor (case_array_type, v);
206*38fd1498Szrj   TREE_STATIC (ctor) = 1;
207*38fd1498Szrj   TREE_PUBLIC (ctor) = 0;
208*38fd1498Szrj   TREE_CONSTANT (ctor) = 1;
209*38fd1498Szrj   TREE_READONLY (ctor) = 1;
210*38fd1498Szrj   DECL_INITIAL (case_array_var) = ctor;
211*38fd1498Szrj   varpool_node::finalize_decl (case_array_var);
212*38fd1498Szrj   add_local_decl (fun, case_array_var);
213*38fd1498Szrj 
214*38fd1498Szrj   gimple_seq seq = NULL;
215*38fd1498Szrj 
216*38fd1498Szrj   if (!useless_type_conversion_p (uint64_type_node, TREE_TYPE (index)))
217*38fd1498Szrj     {
218*38fd1498Szrj       if (TREE_CODE (index) == INTEGER_CST)
219*38fd1498Szrj 	index = fold_convert (uint64_type_node, index);
220*38fd1498Szrj       else
221*38fd1498Szrj 	{
222*38fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_type_cast (uint64_type_node, index));
223*38fd1498Szrj 	  index = gimple_assign_lhs (gimple_seq_last_stmt (seq));
224*38fd1498Szrj 	}
225*38fd1498Szrj     }
226*38fd1498Szrj 
227*38fd1498Szrj   tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_SWITCH);
228*38fd1498Szrj   gimple *gcall = gimple_build_call (fndecl, 2, index,
229*38fd1498Szrj 				     build_fold_addr_expr (case_array_var));
230*38fd1498Szrj   gimple_seq_add_stmt (&seq, gcall);
231*38fd1498Szrj 
232*38fd1498Szrj   gimple_seq_set_location (seq, loc);
233*38fd1498Szrj   gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
234*38fd1498Szrj }
235*38fd1498Szrj 
236*38fd1498Szrj unsigned
sancov_pass(function * fun)237*38fd1498Szrj sancov_pass (function *fun)
238*38fd1498Szrj {
239*38fd1498Szrj   initialize_sanitizer_builtins ();
240*38fd1498Szrj 
241*38fd1498Szrj   /* Insert callback into beginning of every BB. */
242*38fd1498Szrj   if (flag_sanitize_coverage & SANITIZE_COV_TRACE_PC)
243*38fd1498Szrj     {
244*38fd1498Szrj       basic_block bb;
245*38fd1498Szrj       tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_PC);
246*38fd1498Szrj       FOR_EACH_BB_FN (bb, fun)
247*38fd1498Szrj 	{
248*38fd1498Szrj 	  gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb);
249*38fd1498Szrj 	  if (gsi_end_p (gsi))
250*38fd1498Szrj 	    continue;
251*38fd1498Szrj 	  gimple *stmt = gsi_stmt (gsi);
252*38fd1498Szrj 	  gimple *gcall = gimple_build_call (fndecl, 0);
253*38fd1498Szrj 	  gimple_set_location (gcall, gimple_location (stmt));
254*38fd1498Szrj 	  gsi_insert_before (&gsi, gcall, GSI_SAME_STMT);
255*38fd1498Szrj 	}
256*38fd1498Szrj     }
257*38fd1498Szrj 
258*38fd1498Szrj   /* Insert callback into every comparison related operation.  */
259*38fd1498Szrj   if (flag_sanitize_coverage & SANITIZE_COV_TRACE_CMP)
260*38fd1498Szrj     {
261*38fd1498Szrj       basic_block bb;
262*38fd1498Szrj       FOR_EACH_BB_FN (bb, fun)
263*38fd1498Szrj 	{
264*38fd1498Szrj 	  gimple_stmt_iterator gsi;
265*38fd1498Szrj 	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
266*38fd1498Szrj 	    {
267*38fd1498Szrj 	      gimple *stmt = gsi_stmt (gsi);
268*38fd1498Szrj 	      enum tree_code rhs_code;
269*38fd1498Szrj 	      switch (gimple_code (stmt))
270*38fd1498Szrj 		{
271*38fd1498Szrj 		case GIMPLE_ASSIGN:
272*38fd1498Szrj 		  rhs_code = gimple_assign_rhs_code (stmt);
273*38fd1498Szrj 		  if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
274*38fd1498Szrj 		    instrument_comparison (&gsi,
275*38fd1498Szrj 					   gimple_assign_rhs1 (stmt),
276*38fd1498Szrj 					   gimple_assign_rhs2 (stmt));
277*38fd1498Szrj 		  else if (rhs_code == COND_EXPR
278*38fd1498Szrj 			   && COMPARISON_CLASS_P (gimple_assign_rhs1 (stmt)))
279*38fd1498Szrj 		    {
280*38fd1498Szrj 		      tree cond = gimple_assign_rhs1 (stmt);
281*38fd1498Szrj 		      instrument_comparison (&gsi, TREE_OPERAND (cond, 0),
282*38fd1498Szrj 					     TREE_OPERAND (cond, 1));
283*38fd1498Szrj 		    }
284*38fd1498Szrj 		  break;
285*38fd1498Szrj 		case GIMPLE_COND:
286*38fd1498Szrj 		  instrument_comparison (&gsi,
287*38fd1498Szrj 					 gimple_cond_lhs (stmt),
288*38fd1498Szrj 					 gimple_cond_rhs (stmt));
289*38fd1498Szrj 		  break;
290*38fd1498Szrj 
291*38fd1498Szrj 		case GIMPLE_SWITCH:
292*38fd1498Szrj 		  instrument_switch (&gsi, stmt, fun);
293*38fd1498Szrj 		  break;
294*38fd1498Szrj 
295*38fd1498Szrj 		default:
296*38fd1498Szrj 		  break;
297*38fd1498Szrj 		}
298*38fd1498Szrj 	    }
299*38fd1498Szrj 	}
300*38fd1498Szrj     }
301*38fd1498Szrj   return 0;
302*38fd1498Szrj }
303*38fd1498Szrj 
304*38fd1498Szrj template <bool O0> class pass_sancov : public gimple_opt_pass
305*38fd1498Szrj {
306*38fd1498Szrj public:
pass_sancov(gcc::context * ctxt)307*38fd1498Szrj   pass_sancov (gcc::context *ctxt) : gimple_opt_pass (data, ctxt) {}
308*38fd1498Szrj 
309*38fd1498Szrj   static const pass_data data;
310*38fd1498Szrj   opt_pass *
clone()311*38fd1498Szrj   clone ()
312*38fd1498Szrj   {
313*38fd1498Szrj     return new pass_sancov<O0> (m_ctxt);
314*38fd1498Szrj   }
315*38fd1498Szrj   virtual bool
gate(function *)316*38fd1498Szrj   gate (function *)
317*38fd1498Szrj   {
318*38fd1498Szrj     return flag_sanitize_coverage && (!O0 || !optimize);
319*38fd1498Szrj   }
320*38fd1498Szrj   virtual unsigned int
execute(function * fun)321*38fd1498Szrj   execute (function *fun)
322*38fd1498Szrj   {
323*38fd1498Szrj     return sancov_pass (fun);
324*38fd1498Szrj   }
325*38fd1498Szrj }; // class pass_sancov
326*38fd1498Szrj 
327*38fd1498Szrj template <bool O0>
328*38fd1498Szrj const pass_data pass_sancov<O0>::data = {
329*38fd1498Szrj   GIMPLE_PASS,		       /* type */
330*38fd1498Szrj   O0 ? "sancov_O0" : "sancov", /* name */
331*38fd1498Szrj   OPTGROUP_NONE,	       /* optinfo_flags */
332*38fd1498Szrj   TV_NONE,		       /* tv_id */
333*38fd1498Szrj   (PROP_cfg),		       /* properties_required */
334*38fd1498Szrj   0,			       /* properties_provided */
335*38fd1498Szrj   0,			       /* properties_destroyed */
336*38fd1498Szrj   0,			       /* todo_flags_start */
337*38fd1498Szrj   TODO_update_ssa,	     /* todo_flags_finish */
338*38fd1498Szrj };
339*38fd1498Szrj 
340*38fd1498Szrj } // anon namespace
341*38fd1498Szrj 
342*38fd1498Szrj gimple_opt_pass *
make_pass_sancov(gcc::context * ctxt)343*38fd1498Szrj make_pass_sancov (gcc::context *ctxt)
344*38fd1498Szrj {
345*38fd1498Szrj   return new pass_sancov<false> (ctxt);
346*38fd1498Szrj }
347*38fd1498Szrj 
348*38fd1498Szrj gimple_opt_pass *
make_pass_sancov_O0(gcc::context * ctxt)349*38fd1498Szrj make_pass_sancov_O0 (gcc::context *ctxt)
350*38fd1498Szrj {
351*38fd1498Szrj   return new pass_sancov<true> (ctxt);
352*38fd1498Szrj }
353