inclhack.def (suse_linux_vt_cxx): New fix for linux/vt.h being not compatible with...
[official-gcc.git] / gcc / ubsan.c
blob846e884de52f440006665638726fbd54f71b3f6f
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "stor-layout.h"
26 #include "stringpool.h"
27 #include "cgraph.h"
28 #include "tree-pass.h"
29 #include "tree-ssa-alias.h"
30 #include "tree-pretty-print.h"
31 #include "internal-fn.h"
32 #include "gimple-expr.h"
33 #include "gimple.h"
34 #include "gimple-iterator.h"
35 #include "gimple-ssa.h"
36 #include "gimple-walk.h"
37 #include "hashtab.h"
38 #include "output.h"
39 #include "tm_p.h"
40 #include "toplev.h"
41 #include "cfgloop.h"
42 #include "ubsan.h"
43 #include "c-family/c-common.h"
44 #include "rtl.h"
45 #include "expr.h"
47 /* Map from a tree to a VAR_DECL tree. */
49 struct GTY(()) tree_type_map {
50 struct tree_map_base type;
51 tree decl;
54 #define tree_type_map_eq tree_map_base_eq
55 #define tree_type_map_marked_p tree_map_base_marked_p
57 /* Hash from a tree in a tree_type_map. */
59 unsigned int
60 tree_type_map_hash (const void *item)
62 return TYPE_UID (((const struct tree_type_map *)item)->type.from);
65 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
66 htab_t decl_tree_for_type;
68 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
70 static tree
71 decl_for_type_lookup (tree type)
73 /* If the hash table is not initialized yet, create it now. */
74 if (decl_tree_for_type == NULL)
76 decl_tree_for_type = htab_create_ggc (10, tree_type_map_hash,
77 tree_type_map_eq, 0);
78 /* That also means we don't have to bother with the lookup. */
79 return NULL_TREE;
82 struct tree_type_map *h, in;
83 in.type.from = type;
85 h = (struct tree_type_map *)
86 htab_find_with_hash (decl_tree_for_type, &in, TYPE_UID (type));
87 return h ? h->decl : NULL_TREE;
90 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
92 static void
93 decl_for_type_insert (tree type, tree decl)
95 struct tree_type_map *h;
96 void **slot;
98 h = ggc_alloc_tree_type_map ();
99 h->type.from = type;
100 h->decl = decl;
101 slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
102 INSERT);
103 *(struct tree_type_map **) slot = h;
106 /* Helper routine, which encodes a value in the pointer_sized_int_node.
107 Arguments with precision <= POINTER_SIZE are passed directly,
108 the rest is passed by reference. T is a value we are to encode.
109 IN_EXPAND_P is true if this function is called during expansion. */
111 tree
112 ubsan_encode_value (tree t, bool in_expand_p)
114 tree type = TREE_TYPE (t);
115 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
116 if (bitsize <= POINTER_SIZE)
117 switch (TREE_CODE (type))
119 case BOOLEAN_TYPE:
120 case ENUMERAL_TYPE:
121 case INTEGER_TYPE:
122 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
123 case REAL_TYPE:
125 tree itype = build_nonstandard_integer_type (bitsize, true);
126 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
127 return fold_convert (pointer_sized_int_node, t);
129 default:
130 gcc_unreachable ();
132 else
134 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
136 /* The reason for this is that we don't want to pessimize
137 code by making vars unnecessarily addressable. */
138 tree var = create_tmp_var (type, NULL);
139 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
140 if (in_expand_p)
142 rtx mem
143 = assign_stack_temp_for_type (TYPE_MODE (type),
144 GET_MODE_SIZE (TYPE_MODE (type)),
145 type);
146 SET_DECL_RTL (var, mem);
147 expand_assignment (var, t, false);
148 return build_fold_addr_expr (var);
150 t = build_fold_addr_expr (var);
151 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
153 else
154 return build_fold_addr_expr (t);
158 /* Build
159 struct __ubsan_type_descriptor
161 unsigned short __typekind;
162 unsigned short __typeinfo;
163 char __typename[];
165 type. */
167 static tree
168 ubsan_type_descriptor_type (void)
170 static const char *field_names[3]
171 = { "__typekind", "__typeinfo", "__typename" };
172 tree fields[3], ret;
173 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
174 tree flex_arr_type = build_array_type (char_type_node, itype);
176 ret = make_node (RECORD_TYPE);
177 for (int i = 0; i < 3; i++)
179 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
180 get_identifier (field_names[i]),
181 (i == 2) ? flex_arr_type
182 : short_unsigned_type_node);
183 DECL_CONTEXT (fields[i]) = ret;
184 if (i)
185 DECL_CHAIN (fields[i - 1]) = fields[i];
187 TYPE_FIELDS (ret) = fields[0];
188 TYPE_NAME (ret) = get_identifier ("__ubsan_type_descriptor");
189 layout_type (ret);
190 return ret;
193 /* Build
194 struct __ubsan_source_location
196 const char *__filename;
197 unsigned int __line;
198 unsigned int __column;
200 type. */
202 static tree
203 ubsan_source_location_type (void)
205 static const char *field_names[3]
206 = { "__filename", "__line", "__column" };
207 tree fields[3], ret;
208 tree const_char_type = build_qualified_type (char_type_node,
209 TYPE_QUAL_CONST);
211 ret = make_node (RECORD_TYPE);
212 for (int i = 0; i < 3; i++)
214 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
215 get_identifier (field_names[i]),
216 (i == 0) ? build_pointer_type (const_char_type)
217 : unsigned_type_node);
218 DECL_CONTEXT (fields[i]) = ret;
219 if (i)
220 DECL_CHAIN (fields[i - 1]) = fields[i];
222 TYPE_FIELDS (ret) = fields[0];
223 TYPE_NAME (ret) = get_identifier ("__ubsan_source_location");
224 layout_type (ret);
225 return ret;
228 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
229 type with its fields filled from a location_t LOC. */
231 static tree
232 ubsan_source_location (location_t loc)
234 expanded_location xloc;
235 tree type = ubsan_source_location_type ();
237 xloc = expand_location (loc);
239 /* Fill in the values from LOC. */
240 size_t len = strlen (xloc.file);
241 tree str = build_string (len + 1, xloc.file);
242 TREE_TYPE (str) = build_array_type (char_type_node,
243 build_index_type (size_int (len)));
244 TREE_READONLY (str) = 1;
245 TREE_STATIC (str) = 1;
246 str = build_fold_addr_expr (str);
247 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
248 build_int_cst (unsigned_type_node,
249 xloc.line), NULL_TREE,
250 build_int_cst (unsigned_type_node,
251 xloc.column));
252 TREE_CONSTANT (ctor) = 1;
253 TREE_STATIC (ctor) = 1;
255 return ctor;
258 /* This routine returns a magic number for TYPE. */
260 static unsigned short
261 get_ubsan_type_info_for_type (tree type)
263 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
264 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
265 gcc_assert (prec != -1);
266 return (prec << 1) | !TYPE_UNSIGNED (type);
269 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
270 descriptor. It first looks into the hash table; if not found,
271 create the VAR_DECL, put it into the hash table and return the
272 ADDR_EXPR of it. TYPE describes a particular type. WANT_POINTER_TYPE_P
273 means whether we are interested in the pointer type and not the pointer
274 itself. */
276 tree
277 ubsan_type_descriptor (tree type, bool want_pointer_type_p)
279 /* See through any typedefs. */
280 type = TYPE_MAIN_VARIANT (type);
282 tree decl = decl_for_type_lookup (type);
283 /* It is possible that some of the earlier created DECLs were found
284 unused, in that case they weren't emitted and varpool_get_node
285 returns NULL node on them. But now we really need them. Thus,
286 renew them here. */
287 if (decl != NULL_TREE && varpool_get_node (decl))
288 return build_fold_addr_expr (decl);
290 tree dtype = ubsan_type_descriptor_type ();
291 tree type2 = type;
292 const char *tname = NULL;
293 char *pretty_name;
294 unsigned char deref_depth = 0;
295 unsigned short tkind, tinfo;
297 /* Get the name of the type, or the name of the pointer type. */
298 if (want_pointer_type_p)
300 gcc_assert (POINTER_TYPE_P (type));
301 type2 = TREE_TYPE (type);
303 /* Remove any '*' operators from TYPE. */
304 while (POINTER_TYPE_P (type2))
305 deref_depth++, type2 = TREE_TYPE (type2);
307 if (TREE_CODE (type2) == METHOD_TYPE)
308 type2 = TYPE_METHOD_BASETYPE (type2);
311 if (TYPE_NAME (type2) != NULL)
313 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
314 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
315 else
316 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
319 if (tname == NULL)
320 /* We weren't able to determine the type name. */
321 tname = "<unknown>";
323 /* Decorate the type name with '', '*', "struct", or "union". */
324 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
325 if (want_pointer_type_p)
327 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
328 TYPE_VOLATILE (type2) ? "volatile " : "",
329 TYPE_READONLY (type2) ? "const " : "",
330 TYPE_RESTRICT (type2) ? "restrict " : "",
331 TYPE_ATOMIC (type2) ? "_Atomic " : "",
332 TREE_CODE (type2) == RECORD_TYPE
333 ? "struct "
334 : TREE_CODE (type2) == UNION_TYPE
335 ? "union " : "", tname,
336 deref_depth == 0 ? "" : " ");
337 while (deref_depth-- > 0)
338 pretty_name[pos++] = '*';
339 pretty_name[pos++] = '\'';
340 pretty_name[pos] = '\0';
342 else
343 sprintf (pretty_name, "'%s'", tname);
345 switch (TREE_CODE (type))
347 case INTEGER_TYPE:
348 tkind = 0x0000;
349 break;
350 case REAL_TYPE:
351 tkind = 0x0001;
352 break;
353 default:
354 tkind = 0xffff;
355 break;
357 tinfo = get_ubsan_type_info_for_type (type);
359 /* Create a new VAR_DECL of type descriptor. */
360 char tmp_name[32];
361 static unsigned int type_var_id_num;
362 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
363 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
364 dtype);
365 TREE_STATIC (decl) = 1;
366 TREE_PUBLIC (decl) = 0;
367 DECL_ARTIFICIAL (decl) = 1;
368 DECL_IGNORED_P (decl) = 1;
369 DECL_EXTERNAL (decl) = 0;
371 size_t len = strlen (pretty_name);
372 tree str = build_string (len + 1, pretty_name);
373 TREE_TYPE (str) = build_array_type (char_type_node,
374 build_index_type (size_int (len)));
375 TREE_READONLY (str) = 1;
376 TREE_STATIC (str) = 1;
377 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
378 build_int_cst (short_unsigned_type_node,
379 tkind), NULL_TREE,
380 build_int_cst (short_unsigned_type_node,
381 tinfo), NULL_TREE, str);
382 TREE_CONSTANT (ctor) = 1;
383 TREE_STATIC (ctor) = 1;
384 DECL_INITIAL (decl) = ctor;
385 rest_of_decl_compilation (decl, 1, 0);
387 /* Save the VAR_DECL into the hash table. */
388 decl_for_type_insert (type, decl);
390 return build_fold_addr_expr (decl);
393 /* Create a structure for the ubsan library. NAME is a name of the new
394 structure. The arguments in ... are of __ubsan_type_descriptor type
395 and there are at most two of them. MISMATCH are data used by ubsan
396 pointer checking. */
398 tree
399 ubsan_create_data (const char *name, location_t loc,
400 const struct ubsan_mismatch_data *mismatch, ...)
402 va_list args;
403 tree ret, t;
404 tree fields[5];
405 vec<tree, va_gc> *saved_args = NULL;
406 size_t i = 0;
408 /* Firstly, create a pointer to type descriptor type. */
409 tree td_type = ubsan_type_descriptor_type ();
410 TYPE_READONLY (td_type) = 1;
411 td_type = build_pointer_type (td_type);
412 loc = LOCATION_LOCUS (loc);
414 /* Create the structure type. */
415 ret = make_node (RECORD_TYPE);
416 if (loc != UNKNOWN_LOCATION)
418 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
419 ubsan_source_location_type ());
420 DECL_CONTEXT (fields[i]) = ret;
421 i++;
424 va_start (args, mismatch);
425 for (t = va_arg (args, tree); t != NULL_TREE;
426 i++, t = va_arg (args, tree))
428 gcc_checking_assert (i < 3);
429 /* Save the tree arguments for later use. */
430 vec_safe_push (saved_args, t);
431 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
432 td_type);
433 DECL_CONTEXT (fields[i]) = ret;
434 if (i)
435 DECL_CHAIN (fields[i - 1]) = fields[i];
437 va_end (args);
439 if (mismatch != NULL)
441 /* We have to add two more decls. */
442 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
443 pointer_sized_int_node);
444 DECL_CONTEXT (fields[i]) = ret;
445 DECL_CHAIN (fields[i - 1]) = fields[i];
446 i++;
448 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
449 unsigned_char_type_node);
450 DECL_CONTEXT (fields[i]) = ret;
451 DECL_CHAIN (fields[i - 1]) = fields[i];
452 i++;
455 TYPE_FIELDS (ret) = fields[0];
456 TYPE_NAME (ret) = get_identifier (name);
457 layout_type (ret);
459 /* Now, fill in the type. */
460 char tmp_name[32];
461 static unsigned int ubsan_var_id_num;
462 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
463 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
464 ret);
465 TREE_STATIC (var) = 1;
466 TREE_PUBLIC (var) = 0;
467 DECL_ARTIFICIAL (var) = 1;
468 DECL_IGNORED_P (var) = 1;
469 DECL_EXTERNAL (var) = 0;
471 vec<constructor_elt, va_gc> *v;
472 vec_alloc (v, i);
473 tree ctor = build_constructor (ret, v);
475 /* If desirable, set the __ubsan_source_location element. */
476 if (loc != UNKNOWN_LOCATION)
477 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
479 size_t nelts = vec_safe_length (saved_args);
480 for (i = 0; i < nelts; i++)
482 t = (*saved_args)[i];
483 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
486 if (mismatch != NULL)
488 /* Append the pointer data. */
489 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->align);
490 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->ckind);
493 TREE_CONSTANT (ctor) = 1;
494 TREE_STATIC (ctor) = 1;
495 DECL_INITIAL (var) = ctor;
496 rest_of_decl_compilation (var, 1, 0);
498 return var;
501 /* Instrument the __builtin_unreachable call. We just call the libubsan
502 routine instead. */
504 tree
505 ubsan_instrument_unreachable (location_t loc)
507 tree data = ubsan_create_data ("__ubsan_unreachable_data", loc, NULL,
508 NULL_TREE);
509 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
510 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
513 /* Return true if T is a call to a libubsan routine. */
515 bool
516 is_ubsan_builtin_p (tree t)
518 gcc_checking_assert (TREE_CODE (t) == FUNCTION_DECL);
519 return strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
520 "__builtin___ubsan_", 18) == 0;
523 /* Expand UBSAN_NULL internal call. */
525 void
526 ubsan_expand_null_ifn (gimple_stmt_iterator gsi)
528 gimple stmt = gsi_stmt (gsi);
529 location_t loc = gimple_location (stmt);
530 gcc_assert (gimple_call_num_args (stmt) == 2);
531 tree ptr = gimple_call_arg (stmt, 0);
532 tree ckind = gimple_call_arg (stmt, 1);
534 basic_block cur_bb = gsi_bb (gsi);
536 /* Split the original block holding the pointer dereference. */
537 edge e = split_block (cur_bb, stmt);
539 /* Get a hold on the 'condition block', the 'then block' and the
540 'else block'. */
541 basic_block cond_bb = e->src;
542 basic_block fallthru_bb = e->dest;
543 basic_block then_bb = create_empty_bb (cond_bb);
544 if (current_loops)
546 add_bb_to_loop (then_bb, cond_bb->loop_father);
547 loops_state_set (LOOPS_NEED_FIXUP);
550 /* Make an edge coming from the 'cond block' into the 'then block';
551 this edge is unlikely taken, so set up the probability accordingly. */
552 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
553 e->probability = PROB_VERY_UNLIKELY;
555 /* Connect 'then block' with the 'else block'. This is needed
556 as the ubsan routines we call in the 'then block' are not noreturn.
557 The 'then block' only has one outcoming edge. */
558 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
560 /* Set up the fallthrough basic block. */
561 e = find_edge (cond_bb, fallthru_bb);
562 e->flags = EDGE_FALSE_VALUE;
563 e->count = cond_bb->count;
564 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
566 /* Update dominance info for the newly created then_bb; note that
567 fallthru_bb's dominance info has already been updated by
568 split_bock. */
569 if (dom_info_available_p (CDI_DOMINATORS))
570 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
572 /* Put the ubsan builtin call into the newly created BB. */
573 tree fn = builtin_decl_implicit (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH);
574 const struct ubsan_mismatch_data m
575 = { build_zero_cst (pointer_sized_int_node), ckind };
576 tree data = ubsan_create_data ("__ubsan_null_data",
577 loc, &m,
578 ubsan_type_descriptor (TREE_TYPE (ptr), true),
579 NULL_TREE);
580 data = build_fold_addr_expr_loc (loc, data);
581 gimple g = gimple_build_call (fn, 2, data,
582 build_zero_cst (pointer_sized_int_node));
583 gimple_set_location (g, loc);
584 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
585 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
587 /* Unlink the UBSAN_NULLs vops before replacing it. */
588 unlink_stmt_vdef (stmt);
590 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
591 NULL_TREE, NULL_TREE);
592 gimple_set_location (g, loc);
594 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
595 gsi_replace (&gsi, g, false);
598 /* Instrument a member call. We check whether 'this' is NULL. */
600 static void
601 instrument_member_call (gimple_stmt_iterator *iter)
603 tree this_parm = gimple_call_arg (gsi_stmt (*iter), 0);
604 tree kind = build_int_cst (unsigned_char_type_node, UBSAN_MEMBER_CALL);
605 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 2, this_parm, kind);
606 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
607 gsi_insert_before (iter, g, GSI_SAME_STMT);
610 /* Instrument a memory reference. T is the pointer, IS_LHS says
611 whether the pointer is on the left hand side of the assignment. */
613 static void
614 instrument_mem_ref (tree t, gimple_stmt_iterator *iter, bool is_lhs)
616 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
617 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
618 ikind = UBSAN_MEMBER_ACCESS;
619 tree kind = build_int_cst (unsigned_char_type_node, ikind);
620 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 2, t, kind);
621 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
622 gsi_insert_before (iter, g, GSI_SAME_STMT);
625 /* Perform the pointer instrumentation. */
627 static void
628 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
630 gimple stmt = gsi_stmt (gsi);
631 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
632 t = get_base_address (t);
633 const enum tree_code code = TREE_CODE (t);
634 if (code == MEM_REF
635 && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME)
636 instrument_mem_ref (TREE_OPERAND (t, 0), &gsi, is_lhs);
637 else if (code == ADDR_EXPR
638 && POINTER_TYPE_P (TREE_TYPE (t))
639 && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == METHOD_TYPE)
640 instrument_member_call (&gsi);
643 /* Build an ubsan builtin call for the signed-integer-overflow
644 sanitization. CODE says what kind of builtin are we building,
645 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
646 are operands of the binary operation. */
648 tree
649 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
650 tree op0, tree op1)
652 tree data = ubsan_create_data ("__ubsan_overflow_data", loc, NULL,
653 ubsan_type_descriptor (lhstype, false),
654 NULL_TREE);
655 enum built_in_function fn_code;
657 switch (code)
659 case PLUS_EXPR:
660 fn_code = BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW;
661 break;
662 case MINUS_EXPR:
663 fn_code = BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW;
664 break;
665 case MULT_EXPR:
666 fn_code = BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW;
667 break;
668 case NEGATE_EXPR:
669 fn_code = BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW;
670 break;
671 default:
672 gcc_unreachable ();
674 tree fn = builtin_decl_explicit (fn_code);
675 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
676 build_fold_addr_expr_loc (loc, data),
677 ubsan_encode_value (op0, true),
678 op1 ? ubsan_encode_value (op1, true)
679 : NULL_TREE);
682 /* Perform the signed integer instrumentation. GSI is the iterator
683 pointing at statement we are trying to instrument. */
685 static void
686 instrument_si_overflow (gimple_stmt_iterator gsi)
688 gimple stmt = gsi_stmt (gsi);
689 tree_code code = gimple_assign_rhs_code (stmt);
690 tree lhs = gimple_assign_lhs (stmt);
691 tree lhstype = TREE_TYPE (lhs);
692 tree a, b;
693 gimple g;
695 /* If this is not a signed operation, don't instrument anything here.
696 Also punt on bit-fields. */
697 if (!INTEGRAL_TYPE_P (lhstype)
698 || TYPE_OVERFLOW_WRAPS (lhstype)
699 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
700 return;
702 switch (code)
704 case MINUS_EXPR:
705 case PLUS_EXPR:
706 case MULT_EXPR:
707 /* Transform
708 i = u {+,-,*} 5;
709 into
710 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
711 a = gimple_assign_rhs1 (stmt);
712 b = gimple_assign_rhs2 (stmt);
713 g = gimple_build_call_internal (code == PLUS_EXPR
714 ? IFN_UBSAN_CHECK_ADD
715 : code == MINUS_EXPR
716 ? IFN_UBSAN_CHECK_SUB
717 : IFN_UBSAN_CHECK_MUL, 2, a, b);
718 gimple_call_set_lhs (g, lhs);
719 gsi_replace (&gsi, g, false);
720 break;
721 case NEGATE_EXPR:
722 /* Represent i = -u;
724 i = UBSAN_CHECK_SUB (0, u); */
725 a = build_int_cst (lhstype, 0);
726 b = gimple_assign_rhs1 (stmt);
727 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
728 gimple_call_set_lhs (g, lhs);
729 gsi_replace (&gsi, g, false);
730 break;
731 default:
732 break;
736 /* Gate and execute functions for ubsan pass. */
738 static unsigned int
739 ubsan_pass (void)
741 basic_block bb;
742 gimple_stmt_iterator gsi;
744 FOR_EACH_BB (bb)
746 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
748 gimple stmt = gsi_stmt (gsi);
749 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
751 gsi_next (&gsi);
752 continue;
755 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
756 && is_gimple_assign (stmt))
757 instrument_si_overflow (gsi);
759 if (flag_sanitize & SANITIZE_NULL)
761 if (gimple_store_p (stmt))
762 instrument_null (gsi, true);
763 if (gimple_assign_load_p (stmt))
764 instrument_null (gsi, false);
767 gsi_next (&gsi);
770 return 0;
773 static bool
774 gate_ubsan (void)
776 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW);
779 namespace {
781 const pass_data pass_data_ubsan =
783 GIMPLE_PASS, /* type */
784 "ubsan", /* name */
785 OPTGROUP_NONE, /* optinfo_flags */
786 true, /* has_gate */
787 true, /* has_execute */
788 TV_TREE_UBSAN, /* tv_id */
789 ( PROP_cfg | PROP_ssa ), /* properties_required */
790 0, /* properties_provided */
791 0, /* properties_destroyed */
792 0, /* todo_flags_start */
793 TODO_update_ssa, /* todo_flags_finish */
796 class pass_ubsan : public gimple_opt_pass
798 public:
799 pass_ubsan (gcc::context *ctxt)
800 : gimple_opt_pass (pass_data_ubsan, ctxt)
803 /* opt_pass methods: */
804 bool gate () { return gate_ubsan (); }
805 unsigned int execute () { return ubsan_pass (); }
807 }; // class pass_ubsan
809 } // anon namespace
811 gimple_opt_pass *
812 make_pass_ubsan (gcc::context *ctxt)
814 return new pass_ubsan (ctxt);
817 #include "gt-ubsan.h"