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